I am Playing with AC voltage and current measuring using ACS712 and ZMPT101B. I wrote the original code on CCS C for PIC Compiler platform. The measurement is ok but the the "Units" for the quantities are not shifting completely with them on the LCD unless I use manual left/right padding to shift them which add uneccessary lines in the code. Please I Want a guidance here if there is a way for the units to move with the Quatities completly without leaving its leftover on the right when the digits reduced.
For example:
In the above code for AC_Current, will display 5.0 Amps with its unit "A" as 5.0 A instead of 5.0A without a gap betwwen "5.0" and "V" while also AC_Voltage will display 99 Volts with its unit "V" as 99 V instead of 99V without a gap betwwen 99 and "V".
But if the voltage and current become 100th abd 10.0th respectively, it will close the gap as normal as in 10.0A and 220V.
The full code is here below.
#include "LCDSoftI2C.h"
LCDSoftI2C lcd(0x27, 20, 4);
#define ADC_RESOLUTION 1024
float avgResult_ac_voltage = 0;
float avgResult_ac_current = 0;
int16_t AC_Voltage = 0;
float AC_Current = 0.0;
unsigned long previousMillis = 0;
const long interval = 1000;
int sensitivity = 66;
void setup() {
lcd.init();
lcd.backlight();
analogReference(EXTERNAL);
}
void loop() {
unsigned long currentMillis = millis();
//******************************For AC Voltage **************************/
for (int i = 0; i < 8; i++) {
avgResult_ac_voltage += get_ac_voltage();
}
avgResult_ac_voltage = avgResult_ac_voltage / 8.00;
AC_Voltage = 0.3665 * avgResult_ac_voltage;
avgResult_ac_voltage = 0;
//***************************** For AC Current ********************************/
for (int c = 0; c < 8; c++) {
avgResult_ac_current += get_ac_current();
}
avgResult_ac_current = avgResult_ac_current / 8;
AC_Current = (1.75 * avgResult_ac_current) / sensitivity; //ACS712-30A sense = 66
avgResult_ac_current = 0;
char float_str[8];
char CurrStr[21];
char AcStr[21];
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
dtostrf(AC_Current, 2, 1, float_str);
sprintf(CurrStr, "Current: %-4sA", float_str);
lcd.setCursor(0, 0);
lcd.print(CurrStr);
sprintf(AcStr, "AC Out: %-3dV", AC_Voltage);
lcd.setCursor(0, 1);
lcd.print(AcStr);
}
}
//*****************- FUNCTIONS TO READ MAINS VOLTAGE -********************/
unsigned long get_ac_voltage() {
unsigned long acHigh = 0;
unsigned long acLow = ADC_RESOLUTION;
for (uint8_t i = 0; i < 40; i++) {
if (analogRead(A1) > acHigh)
acHigh = analogRead(A1);
if (analogRead(A1) < acLow)
acLow = analogRead(A1);
delayMicroseconds(500);
}
return (acHigh - acLow);
}
//*****************- FUNCTIONS TO READ AC CURRENT -********************/
float get_ac_current() {
float ctValueHigh = 0;
float ctValueLow = ADC_RESOLUTION;
for (uint8_t i = 0; i < 40; i++) {
if (analogRead(A0) > ctValueHigh)
ctValueHigh = analogRead(A0);
if (analogRead(A0) < ctValueLow)
ctValueLow = analogRead(A0);
delayMicroseconds(500);
}
return (ctValueHigh - ctValueLow);
}
You can see for yourself the mess! Please I think you can now fully understand what I mean. Please is there no way I can achieve this only in the sprintf?
Hello house! Please how can I make my Voltage display 03.5V instead of 3.0V ? Then at ten volts is will display 10.0V? This means filling zero/s behind the decreasing digits. Full figure in hundreds will be 100 and 010 in tenths and 001 when it is just 1.
Can someone give me a clue please.
What platform (processor) / board are you using?
All toolsets other that avr-gcc support floating point in their xxprintf() formatting routines "out of the box".
So if not using AVR you can just use sprintf() to get the formatting you desire.
Even better, if not using a platform from Arduino.cc, all the 3rd parties platforms support a printf() method in their Print class, so you can use lcd.printf(....) and it will have floating point support to do what you want.
i.e. if you are using a 3rd party PIC Arduino platform such as the chipkit platform, use the printf() method in the Print class and just switch to using lcd.printf() and get rid of all the dtostrf() and sprintf() stuff.
If you are using an AVR based board and the Arduino.cc platform, you can enable floating point support in the xxprintf() code by altering some compiler/linker options.
You can do this by creating a board type in boards.txt that sets the necessary flags in the board parameters for the appropriate gcc options.
Alternatively, you could modify the platform.txt file for the AVR platform to permanently enable using floating point version of the xxprintf() code for all boards supported by the platform.
getting better xxprintf() support in the AVR platform has been a battle with the Arduino.cc developers and founders for well over 15 years.
They are absolutely dead set on not offering it with the founders claiming that xxprintf() formatting is too confusing and scary for Arduino users.
There have been many proposals and even working code offerings to provide GUI options in the IDE to enable/disable AVR floating point support, and all have been fiercely rejected.
Meanwhile, every single 3rd party core/platform decided to offer a printf() method in their Print class so Arduino.cc is clearly the odd man out.
I am using Arduino unoon Arduino IDE 2.0.4
I coul be able to display float ant integers on the LCD only that I want decreasing numbers to be filling Zero/s behind them as I said that is if the maximum size will be 100, it will display 078 when the value fall to 78 and 006 when the value fall to 6.
Arduino UNO. Bummer.
Those boards are normally handled by the IDE bundled Arduino.cc AVR platform.
It is only platform with no floating point support in xxprintf() by default.
It can be resolved in a few ways, and if it were me, I'd fixed the platform to support floating point so you could at least use sprintf() to do the fixed with formatting (with padding or zero fill).
But that is just my approach since I'm a big believer in using 50 yo formatting APIs rather than have to wonk up the code to deal with and work around less functional/useful APIs.
note: if you have integers then you can use sprintf() for the fixed width formating.
Just use the 0 (zero) fill option.
i.e.
sprintf(buffer, "%03d", counter);
Here is a somewhat recent thread on this never ending issue of lack of xxprintf() capabilities on the Arduino.cc platforms, and more specifically the xxprintf() issues on the Arduino.cc AVR platform:
I have seen what I was looking for. Coming to my original question on how I can make the Units wrap arround the quantities when the number of the digits are decreasing or increasing and then more especially clearing the leftover which is always on the right side when decreasing, I found out that the whole thing is already in the sprintf buffer settings.
Like below:
I removed the "-" sign in "%-4sA" and "%-3dV" and they become "%4sA" and "%3dV" . Like this the V will be following the Voltage from 1V, 10V t0 100V and no left over.
@ bperrybap, I thank you so much for your time. because your post #5 made me dit that.