| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| mcmsat 
 
 
 Joined: 25 May 2018
 Posts: 51
 Location: Nigeria
 
 
			    
 
 | 
			
				| DC Voltmeter Converting From Arduino Platform To CCS C |  
				|  Posted: Sun Jun 30, 2019 9:03 am |   |  
				| 
 |  
				| Hello! My Compiler Ver. 4.140
 As a learning practice,  I have tried my best to covert this Arduino code to CCS C but the LCD could not display the result.
 
 In this code below, the LCD only display "Voltage = 0V"
 
  	  | Code: |  	  | { lcd_goto(1,4);
 printf(lcd_out,"Voltage = %luV",vin);      // I want the Vin to display its value here
 delay_ms(500);
 }
 
 | 
 Please I need help to convert this code to working CCS C code.
 
 The Original Arduino code is enclosed in comment
 
  	  | Code: |  	  | //PIC16F886 with 3-wire LCD Experiments with CCS C Ver. 4.140
 ////////////////////////////////////////////////////////////////////
 /**                                                               //
 //
 #include <LiquidCrystal.h>                                        //
 LiquidCrystal lcd(7, 8, 9, 10, 11, 12);                           //
 int analogInput = 0;                                              //
 float vout = 0.0;                                                 //
 float vin = 0.0;                                                  //
 float R1 = 100000.0; // resistance of R1 (100K) -see text!        //
 float R2 = 10000.0; // resistance of R2 (10K) - see text!         //
 int value = 0;                                                    //
 void setup()                                                      //
 {                                                                 //
 pinMode(analogInput, INPUT);                                   //
 lcd.begin(16, 2);                                              //
 lcd.print("DC VOLTMETER");                                     //
 }                                                                 //
 void loop()                                                       //
 {                                                                 //
 // read the value at analog input                              //
 value = analogRead(analogInput);                               //
 vout = (value * 5.0) / 1024.0; // see text                     //
 vin = vout / (R2/(R1+R2));                                     //
 if (vin<0.09) {                                                //
 vin=0.0;//statement to quash undesired reading !               //
 }                                                                 //
 lcd.setCursor(0, 1);                                              //
 lcd.print("INPUT V= ");                                           //
 lcd.print(vin);                                                   //
 delay(500);                                                       //
 }  /////////////////////////////////////////////////////////////////
 **/
 /**  I wanted to convert the above Arduino code to CCS C Code but VOLTAGE could
 not be displayed. The circuit works fine in Arduino.
 **/
 
 //LCD module connections
 #define LCD_DATA_PIN PIN_B0
 #define LCD_CLOCK_PIN PIN_B1
 #define LCD_EN_PIN PIN_B2
 //End LCD module connections
 
 #include <16F886.h>
 #device ADC = 10
 #fuses HS,NOWDT,NOMCLR,NOPROTECT,NOLVP
 #use delay(clock = 8000000)
 #include <3WireLCD.c>
 
 int16 value =0;
 float vin = 0.0;
 float vout= 0.0;
 float R1 = 100000.0;          // 100k
 float R2 = 10000.0;           // 10k
 
 
 void init()
 {
 setup_adc(ADC_CLOCK_DIV_8);            // 8Tosc ADC conversion time
 setup_adc_ports( sAN0);                // Select Analog Inputs
 delay_ms(10);
 
 set_adc_channel(0);                     //Select AN0 as ADC Input for BV
 delay_ms(1);                            //Wait 1 ms
 value = read_adc();                     //Read AN0 and store in BV
 delay_ms(1);                            //Wait 1 ms
 
 
 }
 
 void main()
 
 {
 lcd_initialize();                      // Initialize LCD module
 delay_ms(100);
 
 lcd_cmd(LCD_CLEAR);                       // Clear the LCD
 
 lcd_goto(5, 1);                              // Go to column 5 row 1
 printf(lcd_out, "DC VOLTMETER");
 
 while(TRUE)
 {
 
 vout = (value* 5.0)/1024.0;
 vin = vout/(R2/(R1+R2));
 
 if (vin<0.09)
 {
 vin=0.0;                       //statement to kill undesired reading !
 }
 {
 lcd_goto(1,4);
 printf(lcd_out,"Voltage = %luV",vin);      // I want the Vin to display its value here
 delay_ms(500);
 }
 }
 }
 
 | 
 _________________
 All is well even in the well!
 |  | 
	
		|  | 
	
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Jun 30, 2019 9:19 am |   |  
				| 
 |  
				| You need to initialize the adc near the start of your main(). Do this one time only.
 You need to read the adc inside your while() loop, at the top of it.
 
 Arduino has a special meaning for the setup() function:
 
  	  | Quote: |  	  | The setup() function is called when a sketch starts. Use it to initialize
 variables, pin modes, start using libraries, etc. The setup() function will
 only run once, after each powerup or reset of the Arduino board.
 
 | 
 The C language does not do this.  It only calls main() when the program
 starts.  If you want to call setup(), you need to put it at the start of main().
 
 You have renamed setup() to init().
 
 Also, look at where the Arduino code below reads the adc. It does it at the
 start of the loop.  It does not do it inside setup().
 
  	  | Quote: |  	  | void loop()
 {
 // read the value at analog input
 value = analogRead(analogInput);
 vout = (value * 5.0) / 1024.0; // see text
 vin = vout / (R2/(R1+R2));
 if (vin<0.09) {
 vin=0.0;//statement to quash undesired reading !
 }
 | 
 
 Last edited by PCM programmer on Sun Jun 30, 2019 10:24 am; edited 1 time in total
 |  | 
	
		|  | 
	
		| dyeatman 
 
 
 Joined: 06 Sep 2003
 Posts: 1968
 Location: Norman, OK
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Jun 30, 2019 10:23 am |   |  
				| 
 |  
				| Unless I am missing it they never called init() to get the adc value to begin with. _________________
 Google and Forum Search are some of your best tools!!!!
 |  | 
	
		|  | 
	
		| mcmsat 
 
 
 Joined: 25 May 2018
 Posts: 51
 Location: Nigeria
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Jun 30, 2019 1:38 pm |   |  
				| 
 |  
				| I inserted "init();", and this has made a difference since I started this experiment! But unfortunately, it displays incorrect value! In the Arduino version, the displayed number in the format:
 " Voltage = 25.8V" or according to the input voltage from 0-55V. but now it displays "Voltage = 4214403V" for 25.8V! Varying the Power supply does not affect the display. It displays an 8 digit numbers base on the initial value of the ADC and can't change in real time .
 
 
  	  | Code: |  	  | void main()
 {
 init();                           // Configure peripherals/hardware
 lcd_initialize();                      // Initialize LCD module
 delay_ms(100);
 
 lcd_cmd(LCD_CLEAR);                       // Clear the LCD
 
 lcd_goto(5, 1);                              // Go to column 5 row 1
 printf(lcd_out, "DC VOLTMETER");
 
 while(TRUE)
 | 
 
 Then another place I think I have another big problem is how to display string characters because if I change:
 
  	  | Code: |  	  | printf(lcd_out,"Voltage = %luV",vin);
 | 
 to
 
  	  | Code: |  	  | printf(lcd_out,"Voltage = %suV",vin);
 | 
 then the display will display 3 digit character I will not understand.
 
 Please I also want an enlightenment on displaying strings
 _________________
 All is well even in the well!
 |  | 
	
		|  | 
	
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 |  | 
	
		|  | 
	
		| mcmsat 
 
 
 Joined: 25 May 2018
 Posts: 51
 Location: Nigeria
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jul 01, 2019 2:47 am |   |  
				| 
 |  
				| 
 
 Hello PCM programmer! You are a great teacher. Just like a pointer in some programs, you pointed to me where my solution is. To tell you honestly, I have been there previously but I couldn't manual until you pointed to me that same place then I believed that is the place...and it it really the place that i had been confused of. I even learnt many other things from there this morning.
 
 You gave me FISHING LINE AND BAIT to catch my own fish instead of giving me fish. god will bless people like you who are helping the less privileged.
 
 My problems as earlier noticed lied in;
 
  	  | Code: |  	  | printf(lcd_out,"Voltage = %xxxV",vin); | 
 
 After reading and understanding the manual I edited it to;
 
 
 
  	  | Code: |  	  | printf(lcd_out,"Voltage = %3.1gV",vin); | 
 
 The program started working but it is not updating is real time. The voltage display only display only the quantity when initialized and could not update in real time. I suspected the the position of ADC conversion and I re-positioned it to stay within the while loop and the program runs perfectly.
 
 Thanks all for helping me.
 _________________
 All is well even in the well!
 |  | 
	
		|  | 
	
		| alan 
 
 
 Joined: 12 Nov 2012
 Posts: 358
 Location: South Africa
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jul 01, 2019 3:04 am |   |  
				| 
 |  
				| You need to add this to your main code, currently you are only reading the ADC once in your init function. 
  	  | Code: |  	  | value = read_adc(); | 
 |  | 
	
		|  | 
	
		| mcmsat 
 
 
 Joined: 25 May 2018
 Posts: 51
 Location: Nigeria
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jul 01, 2019 4:35 am |   |  
				| 
 |  
				|  	  | alan wrote: |  	  | You need to add this to your main code, currently you are only reading the ADC once in your init function. 
  	  | Code: |  	  | value = read_adc(); | 
 | 
 
 I have done that already.
 
 All the problems have been solved before my last post.
 
 Thanks to all again.
 _________________
 All is well even in the well!
 |  | 
	
		|  | 
	
		| alan 
 
 
 Joined: 12 Nov 2012
 Posts: 358
 Location: South Africa
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jul 01, 2019 7:59 am |   |  
				| 
 |  
				| Then post your current code. |  | 
	
		|  | 
	
		| mcmsat 
 
 
 Joined: 25 May 2018
 Posts: 51
 Location: Nigeria
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jul 01, 2019 1:09 pm |   |  
				| 
 |  
				|  	  | alan wrote: |  	  | Then post your current code. | 
 
 Once I am on my system I will do that.
 
 Thanks.
 _________________
 All is well even in the well!
 |  | 
	
		|  | 
	
		| mcmsat 
 
 
 Joined: 25 May 2018
 Posts: 51
 Location: Nigeria
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Jul 02, 2019 7:16 am |   |  
				| 
 |  
				| This is my Final code. It is working as I want it now. Being a newbie as I am, there may be better ways to achieve this, Please lead me to the best way if there is. 
 There is a help I still need here even though it is working for my specified experiment. Sometime I here experts say, "it is better to sample ADC 20 times and work with the Average". This technique of Averaging ADC samples, I understand how important it should be whan thisgs are not steady.
 Please can Someone in this house Insert into my code the AVERAGING FUNCTION? I will appreciate if i learn this through this Same topic I created.
 
 
  	  | Code: |  	  | 
 //PIC16F886 with 3-wire LCD Experiments with CCS C Ver. 4.140
 ////////////////////////////////////////////////////////////////////
 /**                                                               //
 //
 #include <LiquidCrystal.h>                                        //
 LiquidCrystal lcd(7, 8, 9, 10, 11, 12);                           //
 int analogInput = 0;                                              //
 float vout = 0.0;                                                 //
 float vin = 0.0;                                                  //
 float R1 = 100000.0; // resistance of R1 (100K) -see text!        //
 float R2 = 10000.0; // resistance of R2 (10K) - see text!         //
 int value = 0;                                                    //
 void setup()                                                      //
 {                                                                 //
 pinMode(analogInput, INPUT);                                   //
 lcd.begin(16, 2);                                              //
 lcd.print("DC VOLTMETER");                                     //
 }                                                                 //
 void loop()                                                       //
 {                                                                 //
 // read the value at analog input                              //
 value = analogRead(analogInput);                               //
 vout = (value * 5.0) / 1024.0;                                 //
 vin = vout / (R2/(R1+R2));                                     //
 if (vin<0.09) {                                                //
 vin=0.0;//statement to quash undesired reading !               //
 }                                                                 //
 lcd.setCursor(0, 1);                                              //
 lcd.print("INPUT V= ");                                           //
 lcd.print(vin);                                                   //
 delay(500);                                                       //
 }  /////////////////////////////////////////////////////////////////
 **/
 
 /**  The above Arduino code is converted to CCS C Code
 **/
 
 //LCD module connections
 #define LCD_DATA_PIN PIN_B0
 #define LCD_CLOCK_PIN PIN_B1
 #define LCD_EN_PIN PIN_B2
 //End LCD module connections
 
 #include <16F886.h>
 #device ADC = 10
 #fuses HS,NOWDT,NOMCLR,NOPROTECT,NOLVP
 #use delay(clock = 8000000)
 #include <3WireLCD.c>
 
 int16 value =0;
 float vin = 0.0;
 float vout= 0.0;
 float R1 = 100000.0;          // 100k
 float R2 = 10000.0;           // 10k
 
 
 void init()
 {
 setup_adc(ADC_CLOCK_DIV_8);            // 8Tosc ADC conversion time
 setup_adc_ports( sAN0);                // Select Analog Inputs
 delay_ms(10);
 
 }
 
 void main()
 {
 init();                           // Configure peripherals/hardware
 lcd_initialize();                      // Initialize LCD module
 delay_ms(100);
 
 lcd_cmd(LCD_CLEAR);                       // Clear the LCD
 
 lcd_goto(5, 1);                              // Go to column 5 row 1
 printf(lcd_out, "DC VOLTMETER");
 
 while(TRUE)
 
 {
 set_adc_channel(0);                     //Select AN0 as ADC Input for BV
 delay_ms(1);                            //Wait 1 ms
 value = read_adc();                     //Read AN0 and stor in BV
 delay_ms(1);                            //Wait 1 ms
 
 
 vout = (value* 5.0)/1024.0;
 delay_ms(1);
 vin = (vout/(R2/(R1+R2)))+0.05;
 
 if (vin<0.09)
 {
 vin=0.0;                       //statement to kill undesired reading !
 }
 {
 lcd_goto(1,4);                            // Go to column 1 row 4
 printf(lcd_out,"Voltage = %3.1gV",vin);   // Display Voltage Value
 delay_ms(100);
 }
 }
 }
 
 
 | 
 
 
 Another thing I also want to understand is a very newbie question;
 All these delays in LCD statements, are they processed by the HOST controller or the on-board LCD controller? I mean these delays in the code below:
 
  	  | Code: |  	  | void main()
 {
 init();                           // Configure peripherals/hardware
 lcd_initialize();                      // Initialize LCD module
 delay_ms(100);
 
 lcd_cmd(LCD_CLEAR);                       // Clear the LCD
 
 lcd_goto(5, 1);                              // Go to column 5 row 1
 printf(lcd_out, "DC VOLTMETER");
 delay_ms(100);
 
 while(TRUE)
 | 
 
 Thanks in advance.
 _________________
 All is well even in the well!
 |  | 
	
		|  | 
	
		| dluu13 
 
 
 Joined: 28 Sep 2018
 Posts: 395
 Location: Toronto, ON
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Tue Jul 02, 2019 8:27 am |   |  
				| 
 |  
				| An averaging function would look something like this. You'd replace read_adc() with your averaging function in your program. 
 1. read_adc() x number of times
 2. get the sum of all the read_adc() results
 3. divide that sum by x
 
 I'll leave it to you to implement that in an efficient method :D
 
 There's also the "olympic average" method that temtronic sometimes talks about, where you subtract the highest and lowest results out of that big sum of x samples, and then divide by x-2. This helps to get rid of any outrageous outliers.
 |  | 
	
		|  | 
	
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9587
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Jul 02, 2019 9:01 am |   |  
				| 
 |  
				| Olympic average... 
 1) take and store 10 readings,
 2) delete the highest reading
 3) delete the lowest reading
 4) sum the remaining 8 readings
 5) divide the sum by 8 to get average
 
 There's code either in this forum or in the 'code library' forum
 Easy to use the 'search' feature of this site to find them !
 
 Jay
 |  | 
	
		|  | 
	
		| mcmsat 
 
 
 Joined: 25 May 2018
 Posts: 51
 Location: Nigeria
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Jul 02, 2019 12:17 pm |   |  
				| 
 |  
				| @ temtronic 
 I find something like that at post: http://www.ccsinfo.com/forum/viewtopic.php?p=223680
 
 
 
  	  | Code: |  	  | unsigned int16 average; //current average reading
 
 void update_avg(int16 val)
 {
 //call this with your readings. After every ten 'average' will update
 static unsigned int32 sum;
 static unsigned int16 max, min;
 static unsigned int8 ctr=0;
 if (ctr=0)
 {  //first pass update temporary values
 max=0;
 min=65535;
 sum=0;
 }
 sum+=vsl; //add the value to the sum
 if (val>max)
 max=val; //update max stored
 if (val<min)
 min=val; //update min stored
 if (++ctr==10)
 { //on tenth pass
 sum-=max; //subtract highest seen
 sum-=min; //subtract lowest seen
 average=(sum+3)/8; //Now average the 8 value sum (4/5
 //rounding).
 ctr=0; //reset
 }
 }
 | 
 
 Please what does "vsl" stand for in the code?
 
  	  | Code: |  	  | sum+=vsl; //add the value to the sum | 
 
 Thanks
 _________________
 All is well even in the well!
 |  | 
	
		|  | 
	
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9587
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Jul 02, 2019 12:22 pm |   |  
				| 
 |  
				| "vsl" should be "val", it's a 'typo' error. 
 also I'm not to sure how the (sum+3)/8 gives you 4/5 rounding. Hopefully someone can expalin as to me adding 3 to say 65523 doesn't really do much...to adding 3 to say 5 does though !
 
 I'd just average=sum/8
 
 Jay
 |  | 
	
		|  | 
	
		|  |