Hello, I have a program that uses serial reads to take commands from a computer and a switch case to have different commands do different actions. This structure has worked great for most things, however, I am now trying to add a function that if you pass a certain command it will again start waiting for a serial input then read that new command and do something then go back to the initial state.
Specifically this is for a smart battery system using SMBus/I2C where i want to both be able to command it to pull several registers to report them out to the user, but the new command is to program a new serial number in, programming of the serial number into the pack works fine but it had to be hard coded in, i wanted to add a pause and wait for serial to receive the serial number to be programmed by the operator.
The issue i ran into, it pauses without issue but if i include a serial.readbytesuntil in the program switch case it seems to always trigger even if that case is not what is the switch selected.
Here is the Code:
//Include Wire Library
#include <Wire.h>
//Address of Battery
#define Batt_Address 11
//Battery registers
#define temp 0x08
#define volt 0x09
#define curr 0x0A
#define error 0x0C
#define fcc 0x10
#define cycle 0x17
#define chgCurr 0x14
#define chgVolt 0x15
#define desCap 0x18
#define desVolt 0x19
#define serial 0x1C
#define cell1 0x38
#define cell2 0x39
#define cell3 0x3A
#define cell4 0x3B
#define cell5 0x3C
#define cell6 0x3D
#define cell7 0x3E
#define cell8 0x3F
#define MFGACCESS 0x44
#define MFGSERIAL1 0x6D
#define MFGSERIAL2 0x40
#define MFGSERIAL3 0xFF
#define MFGSERIAL4 0xFF
byte MFGSERIAL [] = {0x44, 0x04, 0x6D, 0x40, 0x34, 0xFF};
char chararr[30];
int bufferSize = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Wire.begin();
Wire.setClock(100000);
}
int fetchWord(byte func)
{
uint8_t vals[2] = {0,0};
uint8_t count = 0;
Wire.beginTransmission(Batt_Address);
Wire.write(func);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 2);
while(Wire.available())
{
vals[count++] = Wire.read();
}
return (int)(vals[1]) << 8 | (int)(vals[0]);
}
int fetchWord1(byte func)
{
uint8_t vals[2] = {0,0};
uint8_t count = 0;
Wire.beginTransmission(Batt_Address);
Wire.write(func);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 2);
while(Wire.available())
{
vals[count++] = Wire.read();
}
return (int)(vals[1]) << 8 | (int)(vals[0]);
}
void writeSerial(byte func[])
{
Serial.print(func[1]);
Wire.beginTransmission(Batt_Address);
Wire.write(68);
Wire.write(109);
Wire.write(64);
Wire.write(255);
Wire.write(255);
Wire.endTransmission();
}
void loop() {
while(Serial.available()>0){;
delay(1);
bufferSize = Serial.available();
Serial.readBytesUntil('\n',chararr,bufferSize);
if (isLowerCase(chararr[0])){
chararr[0] = chararr[0] -32; //shift lowercase to uppercase
}
switch (chararr[0]){
case 'P':{
for(int i=0; i<=30; i++){
chararr[i] = '\0';
}
Serial.println("Enter Serial Number");
while(!Serial.available()){;
}
delay(1);
bufferSize = Serial.available();
Serial.readBytesUntil('\n',chararr,bufferSize); // <-- This is the line that seems to cause issue
if (isLowerCase(chararr[0])){
chararr[0] = chararr[0] -32; //shift lowercase to uppercase
}
Serial.println(chararr);
// Wire.beginTransmission(Batt_Address);
// Wire.write(MFGSERIAL,6);
// Wire.endTransmission();
for(int i=0; i<=30; i++){
chararr[i] = '\0';
}
Serial.flush();
break;
}
case 'A':{
Serial.print("Serial Number: ");
Serial.println((unsigned)fetchWord(serial));
Serial.print("Pack Voltage: ");
Serial.println((unsigned)fetchWord(volt));
Serial.print("Cell 1 Voltage: ");
Serial.println(fetchWord(cell1));
Serial.print("Cell 2 Voltage: ");
Serial.println(fetchWord(cell2));
Serial.print("Cell 3 Voltage: ");
Serial.println(fetchWord(cell3));
Serial.print("Cell 4 Voltage: ");
Serial.println(fetchWord(cell4));
Serial.print("Cell 5 Voltage: ");
Serial.println(fetchWord(cell5));
Serial.print("Cell 6 Voltage: ");
Serial.println(fetchWord(cell6));
Serial.print("Cell 7 Voltage: ");
Serial.println(fetchWord(cell7));
Serial.print("Cell 8 Voltage: ");
Serial.println(fetchWord(cell8));
Serial.print("Pack Temp: ");
Serial.println(fetchWord(temp));
Serial.print("Pack Current: ");
Serial.println(fetchWord(curr));
Serial.print("Charging Voltage: ");
Serial.println((unsigned)fetchWord(chgVolt));
Serial.print("Charging Current: ");
Serial.println(fetchWord(chgCurr));
Serial.print("Design Voltage: ");
Serial.println(fetchWord(desVolt));
Serial.print("Design Capacity: ");
Serial.println(fetchWord(desCap));
Serial.print("Cycle Count: ");
Serial.println(fetchWord(cycle));
Serial.print("Max Error: ");
Serial.println(fetchWord(error));
Serial.println();
for(int i=0; i<=30; i++){
chararr[i] = '\0';
}
Serial.flush();
break;
}
default:{
Serial.println(chararr);
for(int i=0; i<=30; i++){
chararr[i] = '\0';
}
Serial.flush();
break;
}
}
}
}
If i comment out the readbytesuntil then all other parts of the code seem to work perfectly.
If i leave that in then no matter what is sent and picked up by the switch case it will only work every other time serial data is passed.
So if i were to send F it will respond F because it goes to the default case, but if i send F again (or anyhting else) it does nothing, then the next time it operates normal. Same thing happens for command A, only every other time that command is sent it will activate pulling the i2c data.
My hunch is the readbytes until is triggering somehow despite not being the case that was selected and leaving an empty chararr so it does nothing. I tried also adding in the P command where it waits for serial to print a repeating ... thinking maybe that was triggering, but that only triggers if P is the command sent.
I had an issue early on in this program where the A function needed to be in {} but the P function has those.
Does anyone have info they could give on using serial read inside a switch statement?
If i break out the serial read to a separate function that the P case calls on will that stop it?
Thanks for any help y'all.
Tim