Nano reads 4 digit numbers as 2-3 digit numbers sometimes.
CODE:
#include <FastLED.h>
// SETTINGS -----------------
#define DEBUG true
#define BAUD_RATE_S 19200
#define DATA_PIN 6
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS 77
#define BRIGHTNESS 70
//---------------------------
#define MX_W 7
#define MX_H 11
#define mxp mxPoint
CRGB leds[NUM_LEDS];
bool ledmask [NUM_LEDS];
int add = 0;
void setup() {
Serial.begin(BAUD_RATE_S);
Serial.setTimeout(10);
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); //init leds
FastLED.setBrightness(BRIGHTNESS);
delay(50); //LED startup delay
FastLED.show();
}
byte adder = 0;
void loop() {
if (Serial.available()) {
String in = Serial.readString();
byte n1 = (in.substring(0, 1)).toInt();
byte n2 = (in.substring(1, 2)).toInt();
byte n3 = (in.substring(2, 3)).toInt();
byte n4 = (in.substring(3, 4)).toInt();
drawBitmap(number[n1], 0, 0, 3, 5);
drawBitmap(number[n2], 4, 0, 3, 5);
drawBitmap(number[n3], 0, 6, 3, 5);
drawBitmap(number[n4], 4, 6, 3, 5);
if (DEBUG) {Serial.println();Serial.println(in);Serial.println(String(n1) + " " + String(n2) + " " + String(n3) + " " + String(n4));Serial.println();}
}
for (int y = 0; y < MX_H; y++) {
for (int x = 0; x < MX_W; x++) {
if (ledmask[mxp(x, y)]) {
leds[mxp(x, y)] = CHSV(y * 10 + adder, 255, 255);
} else {
leds[mxp(x, y)] = CRGB(0, 0, 0);
}
}
}
FastLED.show();
adder++;
}
Example in/out:
[IN ] 1234
[OUT]
[OUT] 12
[OUT]
[OUT] 1 2 0 0
String in = Serial.readString();
byte n1 = (in.substring(0, 1)).toInt();
byte n2 = (in.substring(1, 2)).toInt();
byte n3 = (in.substring(2, 3)).toInt();
byte n4 = (in.substring(3, 4)).toInt();
It it silly to be expecting 4 byte values in a String that is not 4 characters, or more, long. Why are you assuming that the String is 4 characters long?
It is orders of magnitude better to:
- NOT use Strings.
- Use some end of packet marker.
Let's do some calculations.
19200 baud, 8 bits with startbit and stopbit is 1920 bytes per second or 520 µs per byte.
I'm ignoring any Carriage Return or Line Feed, so "1234" takes 2 ms.
A timeout of 10ms should be okay, but there is no hardware buffer. The software has to read the data, so 10ms might be too short.
This is the readString() function: ArduinoCore-avr/Stream.cpp at master · arduino/ArduinoCore-avr · GitHub.
The readInt() and parseFloat() are almost useless for someone who is used to deal better with incoming serial data.
The readString() is the worst. It does not know where the data starts or stops, it reads Carriage Return and Line Feed without knowing what they are. It depends mainly on the timeout.
Do as we do: never use those functions.
Make your own command interpreter.
For and Arduino Nano, you might avoid the String class all together.
I have made an example, but there are many more.
It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).
Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.
...R