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: 1934 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: 357 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: 357 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: 9243 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: 9243 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 |
|
|
|