CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

DC Voltmeter Converting From Arduino Platform To CCS C
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mcmsat



Joined: 25 May 2018
Posts: 51
Location: Nigeria

View user's profile Send private message

DC Voltmeter Converting From Arduino Platform To CCS C
PostPosted: Sun Jun 30, 2019 9:03 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Jun 30, 2019 9:19 am     Reply with quote

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: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Jun 30, 2019 10:23 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Jun 30, 2019 1:38 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Jun 30, 2019 3:16 pm     Reply with quote

Look in the section on printf in the CCS manual.
It gives the different format options for printf.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
mcmsat



Joined: 25 May 2018
Posts: 51
Location: Nigeria

View user's profile Send private message

PostPosted: Mon Jul 01, 2019 2:47 am     Reply with quote

PCM programmer wrote:
Look in the section on printf in the CCS manual.
It gives the different format options for printf.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf



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: 357
Location: South Africa

View user's profile Send private message

PostPosted: Mon Jul 01, 2019 3:04 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Jul 01, 2019 4:35 am     Reply with quote

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: 357
Location: South Africa

View user's profile Send private message

PostPosted: Mon Jul 01, 2019 7:59 am     Reply with quote

Then post your current code.
mcmsat



Joined: 25 May 2018
Posts: 51
Location: Nigeria

View user's profile Send private message

PostPosted: Mon Jul 01, 2019 1:09 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 02, 2019 7:16 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Jul 02, 2019 8:27 am     Reply with quote

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: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jul 02, 2019 9:01 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 02, 2019 12:17 pm     Reply with quote

@ 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: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jul 02, 2019 12:22 pm     Reply with quote

"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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group