Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] CCS PCWH to MicroC Pro porting problem

Status
Not open for further replies.

Veketti

Full Member level 3
Full Member level 3
Joined
Sep 14, 2014
Messages
164
Helped
0
Reputation
0
Reaction score
0
Trophy points
16
Visit site
Activity points
1,700
Dear All,

I bought from Dimensionengineering.com their 3D accelerometer to make G-meter. They have in their web page source code which was made for CCS PCWH compiler. I only have MicroC Pro and I've tried to convert this code to work on microC. So far I've managed to change allmost everything but there's something I'm still missing. When I run the program, on display it says 1. -> 2 -> 3 and keeps repeating that. So I guess display update is working correctly but A/D conversion is not. There are few "setup_" lines which I haven't figured out how to make in microC, perhaps those are the reason why it wont work. I've commented all the original lines that didn't work and added the microC counterpart. As this code was made for the 5g accelerometer I need to change the values to match their 3d accelerometer. Also I planned to include all 3 axes and LCD display.

If you could help me to find what am I still missing I'd be more than happy. I'm not sure am I allowed to paste this code here as the original is available from: https://www.dimensionengineering.com/appnotes/Gmeter/

Here's my porting attempt changes to the original code:
Code:
//Dimension Engineering G meter project
//Written to be compiled on CCS PCWH 3.216
//Do not use for commercial purposes or we will send robots to destroy your homes

//since we don't change the input/output/highZ states
//of the pins at all, using fast IO will save some unnecessary instructions
// #use fast_io(A)
// #use fast_io(B)

#define CALIBRATED_0G 510 //this is the analog value for the zero G point
#define CALIBRATED_SENSITIVITY 19//this number will convert 10bit analog values
                                 //into Gs

//Character data for the 7 seg display. Not all characters get used in this project
#define ONE    0b11011101
#define TWO    0b10101000
#define THREE  0b10011000
#define FOUR   0b11010100
#define FIVE   0b10010010
#define SIX    0b10000010
#define SEVEN  0b11011001
#define EIGHT  0b10000000
#define NINE   0b11010000
#define ZERO   0b10000001
#define DP     0b01111111
#define A      0b11000000
#define B      0b10000110
#define C      0b10100011
#define D      0b10001100
#define E      0b10100010
#define F      0b11100010
#define G      0b10010000
#define BLANK  0b11111111
#define MINUS  0b11111110

//takes an array of three shorts
void update_display(short* tripledigitpointer)
{
   short i;
   short digitarray[13]={ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,A,BLANK,C};
   short digitmask=0b01000000;  //A6 is digit1, A7 is 2, A0 is digit 3
   short output;
   for(i=0;i<3;i++)
   {
//      output_a(digitmask);
//      output=digitarray[tripledigitpointer[i]];
      PORTA = digitmask;
      output=digitarray[tripledigitpointer[i]];
      if(i==0) output=output & DP; //put the decimal point on digit 1
//      output_b(output);
      PORTB = output;

      delay_ms(3);  //lights on most of the time
//      output_b(0xff); //then turn them off to avoid blurring from last digit
      PORTB = 0xff; //then turn them off to avoid blurring from last digit
      delay_us(10);
      digitmask=digitmask<<1; //shifts so next digit is lit
      if(digitmask==0) digitmask++; //for digit 3
   }
}

void main()
{
   short digits[3]={1,2,3};
   int analogvalue=0;
   int oldanalogvalue=0;
   signed int temp=0;
   signed int Gvalue=0;
   short i=0;

//   setup_oscillator(OSC_4MHZ);
//   setup_adc_ports(ALL_ANALOG);    // ANSEL but it this chip doesn't support
//   setup_adc(ADC_CLOCK_DIV_64);
//   setup_spi(FALSE);
//   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
//   setup_timer_1(T1_DISABLED);
//   setup_timer_2(T2_DISABLED,0,1);
   ADCON0 = 0b10010101;     // setting the A/D module. MicroC
//   set_tris_a(0b00111110); //AN1-5 are inputs
//   set_tris_b(0); // all outputs for 7 seg display
   TRISA = 0b00111110; //AN1-5 are inputs
   TRISB = 0; // all outputs for 7 seg display
   adc_init();

   while(1)
   {
      update_display(digits); //calling the display routine multiple times
      update_display(digits); //to slow down how often the data gets updated
      update_display(digits);
      update_display(digits);

//      set_adc_channel(2); //(this is pin 1 on the PIC connected to DE-ACCM's Y output)
      delay_us(10);
//      analogvalue=read_adc();
      analogvalue=ADC_Read(2);
      delay_us(10);
//      analogvalue=read_adc();
      analogvalue+=ADC_Read(2);//take an average of 2 readings to reduce noise
      analogvalue = analogvalue / 2;

      temp = analogvalue-oldanalogvalue;

      if( temp>2 || temp<-2 ) //ignore small changes to make display more readable
      {
         oldanalogvalue=analogvalue;
         //convert analog value into G digits
         Gvalue=analogvalue-CALIBRATED_0G;
         Gvalue=Gvalue<<5;                     //left shifting then dividing allows you to perform
         Gvalue=Gvalue/CALIBRATED_SENSITIVITY; //more precise multiplication/division
         //now convert from the decimal place digits stored in Gvalue
         //to the format of an array of 3 integers
         i=2;
         while(i!=255)
         {
             digits[i]=(short)(Gvalue%10);
             Gvalue=Gvalue/10;
             i--;
         }
      }
   }
}

Thank you in advance. Your kind help is greatly appreciated.

Edit: forgot to mention that for newbie like me this CCS code is easier to understand as those instructions are verbal instead of cryptic microC. Is it just me or others feel the same?
 
Last edited:

Here is the mikroC Code. Only ADCON1 had to be configured.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//Dimension Engineering G meter project
//Written to be compiled on CCS PCWH 3.216
//Do not use for commercial purposes or we will send robots to destroy your homes
 
 
 
#define CALIBRATED_0G 510 //this is the analog value for the zero G point
#define CALIBRATED_SENSITIVITY 19//this number will convert 10bit analog values
                                 //into Gs
 
//Character data for the 7 seg display. Not all characters get used in this project
#define ONE    0b11011101
#define TWO    0b10101000
#define THREE  0b10011000
#define FOUR   0b11010100
#define FIVE   0b10010010
#define SIX    0b10000010
#define SEVEN  0b11011001
#define EIGHT  0b10000000
#define NINE   0b11010000
#define ZERO   0b10000001
#define DP     0b01111111
#define A      0b11000000
#define B      0b10000110
#define C      0b10100011
#define D      0b10001100
#define E      0b10100010
#define F      0b11100010
#define G      0b10010000
#define BLANK  0b11111111
#define MINUS  0b11111110
 
//takes an array of three shorts
void update_display(short* tripledigitpointer)
{
   short i;
   short digitarray[13]={ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,A,BLANK,C};
   short digitmask=0b01000000;  //A6 is digit1, A7 is 2, A0 is digit 3
   short output;
   for(i=0;i<3;i++)
   {
      PORTA = digitmask;
      output = digitarray[tripledigitpointer[i]];
      PORTA = digitmask;
      output = digitarray[tripledigitpointer[i]];
      if(i==0) output=output & DP; //put the decimal point on digit 1
      PORTB = output;
      
      delay_ms(3);  //lights on most of the time
      PORTB = 0xff; //then turn them off to avoid blurring from last digit
            delay_us(10);
      digitmask = digitmask << 1; //shifts so next digit is lit
      if(digitmask == 0) digitmask++; //for digit 3
   }
}
 
void main()
{
   short digits[3]={1,2,3};
   int analogvalue=0;
   int oldanalogvalue=0;
   signed int temp=0;
   signed int Gvalue=0;
   short i=0;
 
 
   ADCON0 = 0b10010101;     // setting the A/D module. MicroC
    ADCON1 = 0xC0;
 
   TRISA = 0b00111110; //AN1-5 are inputs
   TRISB = 0; // all outputs for 7 seg display
   
   while(1)
   {
      update_display(digits); //calling the display routine multiple times
      update_display(digits); //to slow down how often the data gets updated
      update_display(digits);
      update_display(digits);
 
//      set_adc_channel(2); //(this is pin 1 on the PIC connected to DE-ACCM's Y output)
      delay_us(10);
      analogvalue = ADC_Read(2);
      delay_us(10);
      analogvalue += ADC_Read(2);//take an average of 2 readings to reduce noise
      analogvalue = analogvalue / 2;
 
      temp = analogvalue-oldanalogvalue;
 
      if( temp>2 || temp<-2 ) //ignore small changes to make display more readable
      {
         oldanalogvalue=analogvalue;
         //convert analog value into G digits
         Gvalue=analogvalue-CALIBRATED_0G;
         Gvalue=Gvalue<<5;                     //left shifting then dividing allows you to perform
         Gvalue=Gvalue/CALIBRATED_SENSITIVITY; //more precise multiplication/division
         //now convert from the decimal place digits stored in Gvalue
         //to the format of an array of 3 integers
         i=2;
         while(i!=255)
         {
             digits[i]=(short)(Gvalue%10);
             Gvalue=Gvalue/10;
             i--;
         }
      }
   }
}

 
For some reason it still shows 1. -> 2 -> 3 and keeps repeating that. It's not updating the digits.. Originally there were also header file with this:
Code:
#device adc=10 //make the adc work in 10bit mode
#use delay(clock=4000000)
#fuses NOWDT,INTRC_IO, NOPUT, NOMCLR, BROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT

But I've set in "Project" - "Edit project" settings clock 4MHz and also it seems those fuses seem to be the same than on that page oscillator selection: INTRC IO etc. That 10 bit mode I'm not sure how to set, but if I've understood right it should be default 10bit..
 

Files attached.
 

Attachments

  • Accelerometer.zip
    26.6 KB · Views: 88

Unfortunately I don't have Proteus file but I've done the connections according to this:
https://www.dimensionengineering.com/appnotes/Gmeter/schematic.gif
It differs bit to that as VCC and GND on that 3D accelerometer is in different places but the output is connected to the PIC pin 1 / RA2. If I upload the hex file from their web page this device works. Well it shows bit odd values as it's calibrated to 5g unit instead of 3d.
 

Here's the schematics. Display is common anode.
circuit.jpg
 

Okay, I got it. It seems that in CCS all arithmetic types are default unsigned and in micro C signed. So in the last loop, it never got to 255 as it went from 0 to -1. So making the I as unsigned solved this issue. Phew.
 

If I may continue to this as it's still under the same project. I'm using now lcd display and I would like to have other axes to visible too. My guestion is that is it possible to use many inputs for A/D conversion on PICF819? From datasheet it says under ADCON0 that bit 5-3 sets the analog channel select bits and I can choose only one channel.
Code:
CHS2:CHS0: Analog Channel Select bits
000 = Channel 0 (RA0/AN0)
001 = Channel 1 (RA1/AN1)
010 = Channel 2 (RA2/AN2)
011 = Channel 3 (RA3/AN3)
100 = Channel 4 (RA4/AN4)
Is it impossible with this chip?

Or can I make own procedures for all channels and then call them in main one after another to do the conversion? Or I'm only allowed to set ADCONx once in program?

One other thing that I'd like to know that is there any source of information where I could check that what control registers are needed to set to each PIC to make it work. This is my main issue with every new pic as it differs from pic to pic. Eg. Datasheet section which tells you that to operate this pic you need to set at least following registers: xyz, zyx, abc etc..
 

ADC in MCUs are multiplexed. You have to select one channel, read it and then select another channel and read it. You can't read more than one channel simultaneously.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top