float to serial to lcd

I cant seem to get this to work. Ive read many threads and have seen many complicated methods. I need simple.

On arduino #1 (mega):

float Amps;
void setup() {
Serial1.begin(9600);
 }
void loop() {
Serial1.print(Amps);
other stuff;
}

On arduino #2 (nano):
float Amps;
void setup() {
lcd.begin(16,2);
Serial.begin(9600);
}
void loop() {
if (Serial.available()) {
Amps = Serial.read();
lcd.setCursor(0,0);
lcd.print(Amps);
};
other stuff;
[/code]

What's the problem?

Hi,

Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you;

  • tell us what your code is supposed to do.
  • tell us what your code is doing.
  • what model arduino you are using.
  • what version IDE you are using,
  • post you complete code

These bits of information will help us give you quick and accurate answers,

Thanks....Tom.. :slight_smile:

It's a terrible thing, how things that actually work are so complicated. I don't think anyone here can change that. If they could, they all would have done so a long time ago. Some things are more complicated than they really need to be, but that is just due to incompetence or lack of skill. Actually, it's an insidious flaw because the perpetrator rarely realizes or will admit to it. The bottom line is, you will never make that sketch work in the simple way that you have written it. Nobody else can either. You will have to make it more complicated in the process of fixing it. It is the reality of programming in this environment.

This for example:

  Amps = Serial.read();

Serial.read returns one character. You are trying to receive a float. How is that supposed to work?

Serial1.print(Amps) will send text (ascii). So no need to read a float at the other side. If you add a Serial1.print("\n") after printing the Amps, you can have a look at Serial Input Basics - Updated how to read text from the serial port using an endmarker (example 2).

Mega 1280 reads many sensors, one of which is Amps. I want to send this reading to a nano.

Mega:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR    0x3F // <<- Add your address here.
#define Rs_pin  0
#define Rw_pin  1
#define En_pin  2
#define BACKLIGHT_PIN 3
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
int mVperAmp = 125; // use 100 for 20A Module and 66 for 30A Module
int ACSoffset = 2500; 
float Amps = 0;
float Ampbank = 0;
float ahr = 0;
float ah = 100;
float ahs = 100;
float perc = 100;
float RawA;
float e = 0.8;
int timer = 1000;
long hour = 3600000;
int rate;
float dr = 1;
float battvolts = 0;
float battamps = 0;
float solarvolts = 0;
float solaramps = 0;
float ACamps = 0;
int Rawsolaramps;
int Rawsolarvolts;
int Rawbattamps;
int Rawbattvolts;
int RawACamps;
int battampbank = 0;
int battvoltsbank = 0;
int solarvoltsbank = 0;
int solarampsbank = 0;
int ACampsbank = 0;
float battampsV = 0;
float battvoltsV = 0;
float solarvoltsV = 0;
float ACampsV = 0;
float solarampsV = 0;
int solarwatts;
int ACwatts;
void setup() {
  rate = (hour/timer);
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
lcd.begin(20,4);
Serial1.begin(9600);
Serial2.begin(9600);
 }
void loop() {
battampbank = 0;
battvoltsbank = 0;
solarvoltsbank = 0;
solarampsbank = 0;
ACampsbank = 0;
  for (int i = 1;i <= 20;i++){
Rawbattamps = analogRead(A0);
Rawbattvolts = analogRead(A1);
Rawsolarvolts = analogRead(A2);
Rawsolaramps = analogRead(A3);
RawACamps = analogRead(A6);
battampbank = battampbank + Rawbattamps;
battvoltsbank = battvoltsbank + Rawbattvolts;
solarvoltsbank = solarvoltsbank + Rawsolarvolts;
solarampsbank = solarampsbank + Rawsolaramps;
ACampsbank = ACampsbank + RawACamps;
delay(50);
  }
Rawbattamps = battampbank/20;
Rawbattvolts = battvoltsbank/20;  
solarvolts = solarvoltsbank/20;
solaramps = solarampsbank/20;  
ACamps = ACampsbank/20;  
battampsV = (Rawbattamps / 1023.0) * 5000; // Gets you mV
  Amps = ((battampsV - ACSoffset) / mVperAmp);
battvoltsV = (Rawbattvolts / 1023.0) * 5000; // Gets you mV
  battvolts = ((battvoltsV - ACSoffset) / mVperAmp);
solarampsV = (Rawsolaramps / 1023.0) * 5000; // Gets you mV
  solaramps = ((solarampsV - ACSoffset) / mVperAmp);
solarvoltsV = (Rawsolarvolts / 1023.0) * 5000; // Gets you mV
  solarvolts = ((solarvoltsV - ACSoffset) / mVperAmp);
ACampsV = (RawACamps / 1023.0) * 5000; // Gets you mV
  ACamps = ((ACampsV - ACSoffset) / mVperAmp);
if (solarvolts < 0){
    solarvolts = 0;
  };
  if (battvolts < 0){
    battvolts = 0;
  };
  if (solaramps < 0){
    solaramps = 0;
  };
  if (ACamps < 0){
    ACamps = 0;
  };
  solarwatts = solarvolts * solaramps;
  ACwatts = ACamps * 230;


  if (Amps < -90) {
    dr = 0.63;
  }
  else if (Amps < -80) {
    dr = 0.65;
  }
  else if (Amps < -75) {
    dr = 0.67;
  }
  else if (Amps < -70) {
    dr = 0.69;
  }
  else if (Amps < -65) {
    dr = 0.71;
  }
  else if (Amps < -60) {
    dr = 0.73;
  }
  else if (Amps < -55) {
    dr = 0.75;
  }
  else if (Amps < -50) {
    dr = 0.77;
  }
  else if (Amps < -45) {
    dr = 0.79;
  }
  else if (Amps < -40) {
    dr = 0.81;
  }
  else if (Amps < -35) {
    dr = 0.83;
  }
  else if (Amps < -30) {
    dr = 0.85;
  }
  else if (Amps < -25) {
    dr = 0.87;
  }
  else if (Amps < -20) {
    dr = 0.90;
  }
  else if (Amps < -15) {
    dr = 0.93;
  }
  else if (Amps < -10) {
    dr = 0.96;
  }
  else if (Amps < -5) {
    dr = 0.99;
  }
  else if (Amps < 0) {
    dr = 1;
  }
    if (Amps > 0){
    ahr = Amps * e;
       }
     else  if (Amps <= 0){
    ahr = Amps/dr;
            }
  ah = (ah + ahr/rate);
  perc = (ah/ahs)*100;
  if (perc > 100){
    perc = 100;
  };
  if (ah > 100){
    ah = 100;
  };
  Serial1.print(Amps);
  Serial2.print(Amps);
  Serial1.print("A,");
  Serial1.print(ah,3);
  Serial1.print("Ah,");
  Serial1.print(perc); 
  Serial1.print("%,");
  Serial1.print(battvolts);
  Serial1.print("v,");
  Serial1.print(solaramps);
  Serial1.print("A,");
  Serial1.print(solarvolts);
  Serial1.print("v,");
  Serial1.print(solarwatts);
  Serial1.print("w,");
  Serial1.print(ACamps);
  Serial1.print("A,");
  Serial1.print(ACwatts);
  Serial1.println("w");
  lcd.setCursor(0,0);
  lcd.print(Amps);
  lcd.print("A ");
  lcd.setCursor(8,0);
  lcd.print(ah,3);
  lcd.print("Ah ");
  lcd.setCursor(0,1);
  lcd.print(battvolts);
  lcd.print("v ");
  lcd.setCursor(0,2);
  lcd.print(solaramps,1);
  lcd.print("A ");
  lcd.setCursor(7,2);
  lcd.print(solarvolts,1);
  lcd.print("v ");
  lcd.setCursor(15,2);
  lcd.print(solarwatts);
  lcd.print("w ");
  lcd.setCursor(0,3);
  lcd.print(ACamps,2);
  lcd.print("A ");
  lcd.setCursor(15,3);
  lcd.print(ACwatts);
  lcd.print("w ");
  }

Nano:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR    0x27 // <<- Add your address here.
#define Rs_pin  0
#define Rw_pin  1
#define En_pin  2
#define BACKLIGHT_PIN 3
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
float Amps = 0;
const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

void setup() {
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
lcd.begin(16,2);  
   pinMode(5, OUTPUT); 
   digitalWrite(5, LOW); 
   pinMode(6, OUTPUT); 
   digitalWrite(6, LOW); 
   pinMode(7, OUTPUT); 
   digitalWrite(7, LOW); 
   pinMode(8, OUTPUT); 
   digitalWrite(8, LOW); 
   pinMode(9, OUTPUT); 
   digitalWrite(9, LOW); 
   pinMode(10, OUTPUT); 
   digitalWrite(10, LOW); 
   pinMode(11, OUTPUT); 
   digitalWrite(11, LOW); 
   pinMode(12, OUTPUT); 
   digitalWrite(12, LOW); 
   Serial.begin(9600);
 }
void loop() {
 if (Serial.available()) {
  Amps = Serial.read();
 lcd.setCursor(0,0);
 lcd.print(Amps);
  };
 if (Amps <= 3) {
    if (digitalRead(12) == HIGH){
    digitalWrite(12, LOW);
    }
    else if (digitalRead(11) == HIGH){
    digitalWrite(11, LOW);
    }
    else if (digitalRead(10) == HIGH){
    digitalWrite(10, LOW);
    }
    else if (digitalRead(9) == HIGH){
    digitalWrite(9, LOW);
    }
    else if (digitalRead(8) == HIGH){
    digitalWrite(8, LOW);
    }
    else if (digitalRead(7) == HIGH){
    digitalWrite(7, LOW);
    }
    else if (digitalRead(6) == HIGH){
    digitalWrite(6, LOW);
    }
    else if (digitalRead(5) == HIGH){
    digitalWrite(5, LOW);
    }
    else {
      digitalWrite(5, LOW);
    };
    
      }
     else if (Amps > 3) { 
       if (digitalRead(5) == LOW){
    digitalWrite(5, HIGH);
    }
    else if (digitalRead(6) == LOW){
    digitalWrite(6, HIGH);
    }
    else if (digitalRead(7) == LOW){
    digitalWrite(7, HIGH);
    }
    else if (digitalRead(8) == LOW){
    digitalWrite(8, HIGH);
    }
    else if (digitalRead(9) == LOW){
    digitalWrite(9, HIGH);
    }
    else if (digitalRead(10) == LOW){
    digitalWrite(10, HIGH);
    }
    else if (digitalRead(11) == LOW){
    digitalWrite(11, HIGH);
    }
    else if (digitalRead(12) == LOW){
    digitalWrite(12, HIGH);
    }
    else {
      digitalWrite(12, HIGH);
    };
         }
         lcd.setCursor(0,0);
  lcd.print(Amps);
  lcd.setCursor(0,1);
  lcd.print(digitalRead(5));
  lcd.print(digitalRead(6));
  lcd.print(digitalRead(7));
  lcd.print(digitalRead(8));
  lcd.print(digitalRead(9));
  lcd.print(digitalRead(10));
  lcd.print(digitalRead(11));
  lcd.print(digitalRead(12));
}

Northland:
Mega 1280 reads many sensors, one of which is Amps. I want to send this reading to a nano.

Reply #4 will do that.

Riiiiiiiiiight.
You mean example 2. With FOURTY SEVEN lines of code. Just to send a number from one arduino to another?

And yet, on Serial.print() - Arduino Reference it states
"Floats are similarly printed as ASCII digits, defaulting to two decimal places" which certainly does not imply 47 lines of code are required.

So again I ask: is there not an easier way?
A reduction in sarcasm, arrogance, condescending tone, insults and hostility would be appreciated.

Hopefully those googling this from now on will find this
Mega:

Serial2.print(Amps);
  Serial2.print('\n');

Nano:

if(Serial.available() > 0) {
        str = Serial.readStringUntil('\n');
        Amps = str.toFloat();
        lcd.print(Amps);
      }

There. 6 lines of code.

You're using the String class. It it well known for causing random crashes due to the heap fragmentation caused by dynamic memory allocation in the absence of a robust garbage collector. If you can tolerate that risk, then fine.

Also, unless I am mistaken, readStringUntil() is a blocking function, which is the kiss of death for a realtime application.

Northland:
Riiiiiiiiiight.
You mean example 2. With FOURTY SEVEN lines of code. Just to send a number from one arduino to another?

You can’t count :wink: The actual recvWithEndMarker() is only TWENTY-TWO lines :slight_smile:

Northland:
And yet, on https://www.arduino.cc/en/Serial/Print it states
“Floats are similarly printed as ASCII digits, defaulting to two decimal places” which certainly does not imply 47 lines of code are required.

How do you get to the conclusion that that does not require 47 lines?

Northland:
Mega:

Serial2.print(Amps);

Serial2.print(’\n’);

As I said, add a newline (I used “\n” but that’s basically the same).

Northland:
Nano:

if(Serial.available() > 0) {

str = Serial.readStringUntil(’\n’);
        Amps = str.toFloat();
        lcd.print(Amps);
      }



There. 6 lines of code.

Great. Just for your information, readStringUntil is actually 11 lines of code and calls timedRead which is another 10 lines of code. So Robin’s code did not do to badly :slight_smile:

Although this might work for the current setup, be aware that this will not always work.
The pitfalls:
1)
What happens if you don’t receive the ‘\n’ in time? Not likely with your current sending code but something to be aware of. Therefor it might actually be better to use the example with startmarker and endmarker. That way you can guarantee that you received a full message; yes, that will be more lines of code.
2)
The use of String (capital S) which can result in difficult to trace undefined behaviour due to memory issues. It’s not said that that will be the case in this scenario, but don’t come crying that it crashes after 2 hours or 2 days or …
You might be better of using readBytesUntil() and atof().

And a last thing: you pissed away 1.5 kByte of code memory. Not an issue now probably but for other projects it might be.

Based on your code, the following sketch.

void setup() {
  Serial.begin(9600);
}

void loop() {
  String str;
  float Amps;
  
  if (Serial.available() > 0) {
    str = Serial.readStringUntil('\n');
    Amps = str.toFloat();
    //lcd.print(Amps);
    Serial.println(Amps);
  }
}

Compile information

Sketch uses 6,588 bytes (20%) of program storage space. Maximum is 32,256 bytes.
Global variables use 213 bytes (10%) of dynamic memory, leaving 1,835 bytes for local variables. Maximum is 2,048 bytes.

A sketch loosely based on example 2 of the Serial Input Basics thread.

void setup() {
  Serial.begin(9600);
}

void loop()
{
  char *str;
  float Amps;
  unsigned long startTime = 0;

  // start time for timeout
  startTime = millis();
  while (millis() - startTime < 1000)
  {
    // read a string (lower case s) character by character
    str = readSerial();
    // if complete
    if (str != NULL)
      break;
  }
  // if complete
  if (str != NULL)
  {
    Amps = atof(str);
    //lcd.print(Amps);
    Serial.println(Amps);
  }
}

char *readSerial()
{
  static char buffer[10];
  static char index = 0;

  if (index == 0)
  {
    // 'empty' buffer
    buffer[0] = '\0';
  }

  // if data available and buffer not full
  if (Serial.available() > 0 && index < sizeof(buffer))
  {
    // read a character
    buffer[index] = Serial.read();
    // if endmarker
    if (buffer[index] == '\n')
    {
      // terminate with nul character
      buffer[index] = '\0';
      // for the next time, we start at zero again
      index = 0;
      // return buffer
      return buffer;
    }
    // indecrement index so it points to next free position
    index++;
  }
  // not complete yet
  return NULL;
}

Compile information

Sketch uses 4,904 bytes (15%) of program storage space. Maximum is 32,256 bytes.
Global variables use 214 bytes (10%) of dynamic memory, leaving 1,834 bytes for local variables. Maximum is 2,048 bytes.

And a sketch based on readBytesUntil (not tested)

void setup() {
 Serial.begin(9600);
}

void loop() {
 char buffer[10];
 float Amps;

 if (Serial.available() > 0) {
   Serial.readBytesUntil('\n', buffer, 10);
   bool fIsValid = false;
   // make sure that we have a nul character
   for (int cnt = 0; cnt < sizeof(buffer); cnt++)
   {
     if (buffer[cnt] == '\n')
       buffer[cnt] = '\0';
     if (buffer[cnt] == '\0')
       fIsValid = true;
   }
   // only if we have a nul character
   if (fIsValid == true)
   {
     Amps = atof(buffer);
     //lcd.print(Amps);
     Serial.println(Amps);
   }
 }
}

Compile information

Sketch uses 5,050 bytes (15%) of program storage space. Maximum is 32,256 bytes.
Global variables use 209 bytes (10%) of dynamic memory, leaving 1,839 bytes for local variables. Maximum is 2,048 bytes.

It’s your call; if you don’t want to do all the typing, the last option is probably the optimum between amount of typing and code size (if you don’t care about blocking).

One additional note:

Hardening code to make sure that it behaves exactly as needed costs lines of code. I write quite a bit of Windows code. Ask a user to enter a number between zero and hundred in a textbox or on the command line and they will type abcdef (on purpose or by accident). If you don’t harden the code, you end with ‘unhandled exceptions’.

First you need to handle that it might not be a numeric value which will take at least 4 or 5 lines of code. Next you need to verify that it is indeed between 0 and 100 (both included) and tell the user that he is an idiot if he did not enter that. Another 4 or 5 lines of code.

And you need to handle what to do if it was not correct (at least another line of code).

A simple basic program can start with 20 or 30 lines of code. Once you’re done catering properly for all possible error conditions, you are at 200 lines. This applies to ANY programming environment (embedded like Arduino, Linux, Windows, …) and any language (and the lower level it is, the more careful you have to be).