Complimentary Qt Forum post: QSerialPort not reading from Arduino | Qt Forum
Hi. I have the following code on the Arduino Uno:
void setup() {
// put your setup code here, to run once:
Serial.begin(115200); // usb port serial
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
//Collect data.
bool readyRead = true;
int i = 0;
//Serial.println("Serial available.");
if (Serial.available() > 0) {
//Serial.println("Serial available.");
i = msgReceiver('\n', readyRead); //msgReceiver is for turning the input to a char array. '\n' is end char. The output of msgReceiver is the char array position, so need to ++.
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //This turns an LED on and off.
messageArray[27] = '\0'; // terminate the string
int msgLength = i + 1;
for (i = msgLength; i > 22; i--) { //messageArray[22] is the 2nd char of the checkSum. Should not be ablated.
messageArray[i] = '\0';
}
bool canSend = true;
char checkSumCharacters[2] = {messageArray[i - 1], messageArray[i]}; //Values are ascii code of the base16 numbers.
int receivedCheckSum = strtoul(checkSumCharacters, NULL, 16); //Converts the base16 characters to an int.
int checkSum = checkSumGenerator(messageArray);
for (i = 0; i < sizeof(cmdtarget); i++) { //Length of cmdtarget is 5.
cmdtarget[i] = messageArray[i];
}
cmdtarget[5] = '\0';
for (i = 0; i < sizeof(input_cmdtype) - 1; i++) { //Length of cmdtype is 5.
input_cmdtype[i] = messageArray[i + 6];
}
input_cmdtype[5] = '\0';
for (i = 0; i < sizeof(input_cmdparam) - 1; i++) { //Length of cmdparam is 8.
input_cmdparam[i] = messageArray[i + 12];
}
input_cmdparam[8] = '\0';
//An attempt at a function pointer to be called for rtnProtocols. Pointer used to decrease negative effects of conditionals.
stringFunction *rtnpointer[] = {
FIRMV_F, VALCN_F, RQSPC_F, CTFTC_F, LIDVM_F, LIDVC_F, PREVC_F, STPWM_F, CHPWM_F, STPER_F, CHPER_F, CHIGH_F, SHIGH_F, MOTST_F, MHIGH_F, MTRTT_F,
RCTIC_F, RCTGM_F, RCTGC_F, SAVEA_F, PREST_F, PREND_F, RQPRE_F, CLPRE_F, RQDAT_F, CUPTC_F, LIDTC_F, CURPR_F, CUPTT_F, CDATE_F, CTIME_F, SDATE_F, RDTTM_F,
SPROG_F, SLOAD_F, CUFAC_F, LIFAC_F, STFAC_F, MTFAC_F, PPFAC_F, PCOFF_F, CUPFM_F, CUPFC_F, LIDFM_F, LIDFC_F, PREFC_F, FCPWM_F, FCPER_F, FHIGH_F,
};
input in = convert(input_cmdtype); //Using the char to enum converter.
canSend = errorStack(cmdtarget, receivedCheckSum, checkSum, msgLength, in, canSend);
if (canSend) {
char verak[6] = "VERAK";
rtnProtocols(verak, input_cmdparam);
rtnpointer[in](input_cmdtype, input_cmdparam);
}
}
}
//Reads message.
int msgReceiver(char endMarker, bool readyRead) {
char rc;
int ndx = 0;
while (readyRead == true) {
if (Serial.available() > 0) {
rc = Serial.read();
if (rc != endMarker) {
messageArray[ndx] = rc;
ndx++;
}
else if (rc == endMarker) {
messageArray[ndx] = '\0'; // terminate the string
//Serial.println("Received \n.");
rc = 0;
readyRead = false;
}
else {
readyRead = true;
}
}
}
return ndx;
}
//Function write back to PC
void rtnProtocols(char cmdtype[], char cmdparam[]) {
char outputString[28] = "TOWST_";
strcat (outputString, cmdtype);
strcat (outputString, "_");
strcat (outputString, cmdparam);
strcat (outputString, "_");
int outputCheckSum = checkSumGenerator(outputString);
char outputCheckSumHex[3] = "00";
itoa (outputCheckSum, outputCheckSumHex, 16);
if (outputCheckSum < 16) { //Adds a 0 if CS has fewer than 2 numbers
outputCheckSumHex[1] = outputCheckSumHex[0];
outputCheckSumHex[0] = '0';
}
outputCheckSumHex[0] = toupper (outputCheckSumHex[0]);
outputCheckSumHex[1] = toupper (outputCheckSumHex[1]);
strcat (outputString, outputCheckSumHex); //Now displayed in base16
outputString[23] = {'\r'}; //Not displayed in port. This should be happening, I think.
outputString[24] = {'\n'};
Serial.write(outputString);
}
(The full code will be at the bottom of this post)
When I send a message through to the Arduino code from the Arduino serial monitor, the code does successfully process the message and return it on the Arduino serial monitor. However, when sending messages through to the code via a custom Qt application, the code no longer processes the message and returns it to the Qt application at baud rates higher than 9600.
My Qt code, if it helps:
//attempts a connection with the next device in the list of available ports
void DeviceConnection::connectDevice()
{
serialPort_Controller->close();
portsAvailable = QSerialPortInfo::availablePorts();
qDebug() << "connecting";
qDebug() << portsAvailable.count();
QSerialPortInfo port;
if (currentPosInList < portsAvailable.count())
{
portName = portsAvailable.at(currentPosInList).portName();
qDebug() << portName;
serialPort_Controller->setPortName(portName); //My computer
serialPort_Controller->setBaudRate(115200);
serialPort_Controller->setDataBits(QSerialPort::Data8);
serialPort_Controller->setParity(QSerialPort::NoParity);
serialPort_Controller->setStopBits(QSerialPort::OneStop);
serialPort_Controller->setFlowControl(QSerialPort::SoftwareControl);
currentPosInList++;
if(serialPort_Controller->open(QIODevice::ReadWrite))
{
qDebug() << "Connected";
int i = serialPort_Controller->write("TOPIC_VALCN_00000000_48\r\n"); //"TOPIC_VALCN_00000000_48\r\n"
qDebug() << i;
qDebug() << "TOPIC_VALCN_00000000_48\r\n";
}
else
{
qDebug() << "Connection error";
}
if (!serialPort_Controller->isOpen())
{
qDebug() << "Cannot open controller serial port";
}
}
else
{
currentPosInList = 0;
}
}
//received messages get processed here into the correct format
void DeviceConnection::serialReady()
{
QString allReceived = QString(serialPort_Controller->readAll());
// if (SystemSettings::get()->getValue(PROTOCOL_DEBUG_MODE) == "1")
// backSerialPort->write(allReceived.toUtf8());
qDebug() << "recieved messages: " << allReceived;
allReceived = incomingRemainder + allReceived;
QStringList fullMessages = allReceived.split("\r\n");
incomingRemainder = fullMessages.last();
fullMessages.removeLast();
foreach (QString message, fullMessages) {
//qDebug() << message; For seeing the message on debugs.
emit receivedMessage(message);
}
}
Things I've attempted, two of which kinda worked:
1: Changing the data bits and baud rates. Changing the databits did not work, but changing the baud rate to 9600 worked.
2: Using a different Uno. That did not work and the same problem persisted.
3: Adding a delay here:
void loop() {
//Collect data.
//char endMarker = '\n';
bool readyRead = true;
int i = 0;
//digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
//Serial.println("Serial available.");
if (Serial.available() > 0) {
//Serial.println("Serial available.");
i = msgReceiver('\n', readyRead); //msgReceiver is for turning the input to a char array. '\n' is end char. The output of msgReceiver is the char array position, so need to ++.
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //This turns an LED on and off.
messageArray[27] = '\0'; // terminate the string
delay(200);
This did not work.
4: Adding another Serial.println here:
void loop() {
//Collect data.
//char endMarker = '\n';
bool readyRead = true;
int i = 0;
//digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
//Serial.println("Serial available.");
if (Serial.available() > 0) {
//Serial.println("Serial available.");
i = msgReceiver('\n', readyRead); //msgReceiver is for turning the input to a char array. '\n' is end char. The output of msgReceiver is the char array position, so need to ++.
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //This turns an LED on and off.
messageArray[27] = '\0'; // terminate the string
Serial.println("11111");
This worked. I don't know why.
I have looked into the Serial.println documentation and was unable to find anything apparently relevant to this situation. Please let me know if more information is required.
Full code:
#define EXPECTED_MSGLENGTH 25 //23 char message, plus '/r' and '/n', each 1 char in length.
char input_cmdtype[6]; //The 5-letter command
char input_cmdparam[9]; //The 8-digit data thingy
char messageArray[28];
char cmdtarget[6];
typedef void stringFunction(char cmdtype[6], char cmdparam[9]); //Update this, update the switch-case file, update the converter, and add the function
enum input {FIRMV, VALCN, RQSPC, CTFTC, LIDVM, LIDVC, PREVC, STPWM, CHPWM, STPER, CHPER, CHIGH, SHIGH, MOTST, MHIGH, MTRTT, RCTIC, RCTGM,
RCTGC, SAVEA, PREST, PREND, RQPRE, CLPRE, RQDAT, CUPTC, LIDTC, CURPR, CUPTT, CDATE, CTIME, SDATE, RDTTM, SPROG, SLOAD, CUFAC, LIFAC,
STFAC, MTFAC, PPFAC, PCOFF, CUPFM, CUPFC, LIDFM, LIDFC, PREFC, FCPWM, FCPER, FHIGH, INVAL
};
input convert(char str[]) { //A char to enum converter.
switch (str[0]) {
case 'C':
if (str[1] == 'U') {
if (strcmp (str, "CUPTC") == 0) return CUPTC;
else if (strcmp (str, "CURPR") == 0) return CURPR;
else if (strcmp (str, "CUPTT") == 0) return CUPTT;
else if (strcmp (str, "CUFAC") == 0) return CUFAC;
else if (strcmp (str, "CUPFM") == 0) return CUPFM;
else if (strcmp (str, "CUPFC") == 0) return CUPFC;
}
else if (str[1] == 'H') {
if (strcmp (str, "CHPER") == 0) return CHPER;
else if (strcmp (str, "CHIGH") == 0) return CHIGH;
else if (strcmp (str, "CHPWM") == 0) return CHPWM;
}
else if (strcmp (str, "CLPRE") == 0) return CLPRE;
else if (strcmp (str, "CDATE") == 0) return CDATE;
else if (strcmp (str, "CTIME") == 0) return CTIME;
else if (strcmp (str, "CTFTC") == 0) return CTFTC;
else return INVAL;
break;
case 'F':
if (strcmp (str, "FIRMV") == 0) return FIRMV;
else if (strcmp (str, "FCPWM") == 0) return FCPER;
else if (strcmp (str, "FCPER") == 0) return FCPER;
else if (strcmp (str, "FHIGH") == 0) return FHIGH;
else return INVAL;
break;
case 'L':
if (str[2] == 'D') {
if (strcmp (str, "LIDVM") == 0) return LIDVM;
else if (strcmp (str, "LIDVC") == 0) return LIDVC;
else if (strcmp (str, "LIDTC") == 0) return LIDTC;
else if (strcmp (str, "LIDFM") == 0) return LIDFM;
else if (strcmp (str, "LIDFC") == 0) return LIDFM;
}
else if (strcmp (str, "LIFAC") == 0) return LIFAC;
else return INVAL;
break;
case 'P':
if (str[1] == 'R') {
if (strcmp (str, "PREVC") == 0) return PREVC;
else if (strcmp (str, "PREST") == 0) return PREST;
else if (strcmp (str, "PREND") == 0) return PREND;
else if (strcmp (str, "PREFC") == 0) return PREFC;
}
else if (strcmp (str, "PPFAC") == 0) return PPFAC;
else if (strcmp (str, "PCOFF") == 0) return PCOFF;
else return INVAL;
break;
case 'S':
if (str[1] == 'T') {
if (strcmp (str, "STFAC") == 0) return STFAC;
else if (strcmp (str, "STPER") == 0) return STPER;
else if (strcmp (str, "STPWM") == 0) return STPWM;
else if (strcmp (str, "STFAC") == 0) return STFAC;
}
else if (strcmp (str, "SHIGH") == 0) return SHIGH;
else if (strcmp (str, "SDATE") == 0) return SDATE;
else if (strcmp (str, "SPROG") == 0) return SPROG;
else if (strcmp (str, "SLOAD") == 0) return SLOAD;
else if (strcmp (str, "SAVEA") == 0) return SAVEA;
else return INVAL;
break;
case 'R':
if (str[1] == 'Q') {
if (strcmp (str, "RQSPC") == 0) return RQSPC;
else if (strcmp (str, "RQPRE") == 0) return RQPRE;
else if (strcmp (str, "RQDAT") == 0) return RQDAT;
}
if (str[1] == 'C') {
if (strcmp (str, "RCTIC") == 0) return RCTIC;
else if (strcmp (str, "RCTGM") == 0) return RCTGM;
else if (strcmp (str, "RCTGC") == 0) return RCTGC;
}
else if (strcmp (str, "RDTTM") == 0) return RDTTM;
else return INVAL;
break;
case 'M':
if (strcmp (str, "MTFAC") == 0) return MTFAC;
else if (strcmp (str, "MOTST") == 0) return MOTST;
else if (strcmp (str, "MHIGH") == 0) return MHIGH;
else if (strcmp (str, "MTRTT") == 0) return MTRTT;
else return INVAL;
break;
case 'V':
if (strcmp (str, "VALCN") == 0) return VALCN;
else return INVAL;
break;
default:
return INVAL;
}
}
//Executing protocols.
void FIRMV_F(char output_cmdtype[], char output_cmdparam[]) { //Get firmware version number
strcpy(output_cmdparam, "01050A00"); //In the unlikely event strcpy stops working, switch to strncpy().
//Serial.println(output_cmdparam);
rtnProtocols(output_cmdtype, output_cmdparam); //Combines TOWST, cmdtype, cmdparam, generates a CS, then adds \r\n. See desktop code for reason why output_cmdparam is what it is.
}
void VALCN_F(char output_cmdtype[], char output_cmdparam[]) { //Get Connection verification
rtnProtocols(output_cmdtype, output_cmdparam);
}
void RQSPC_F(char output_cmdtype[], char output_cmdparam[]) { //Get device information (i.e. serial num, last date calibrated, etc. See protocol doc for full list.)
strcpy(output_cmdtype, "GVSPC"); //Send device info signal
strcpy(output_cmdparam, "00101201"); //cmdparam is serial number
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "30082022"); //cmdparam is date of lid calibration
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "16062019"); //cmdparam is date of cup calibration
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "01072003"); //cmdparam is date of pressure calibration
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "ENSPC"); //Send device info signal.
strcpy(output_cmdparam, "00000000");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CTFTC_F(char output_cmdtype[], char output_cmdparam[]) { //Get m value for lid temperature calibration
rtnProtocols(output_cmdtype, output_cmdparam);
}
void LIDVM_F(char output_cmdtype[], char output_cmdparam[]) { //Get m value for lid temperature calibration
strcpy(output_cmdtype, "LIDVM");
strcpy(output_cmdparam, "3F7DBA0A");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void LIDVC_F(char output_cmdtype[], char output_cmdparam[]) { //Get c value for lid temperature calibration
strcpy(output_cmdparam, "3F7DBA0A");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void PREVC_F(char output_cmdtype[], char output_cmdparam[]) { //Get calibration constant c for pressure
strcpy(output_cmdparam, "3F7DBA0A");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void STPWM_F(char output_cmdtype[], char output_cmdparam[]) { //Sets the PWM of the air pump
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CHPWM_F(char output_cmdtype[], char output_cmdparam[]) { //Instructs the air pump to turn on with the PWM value specified
rtnProtocols(output_cmdtype, output_cmdparam);
}
void STPER_F(char output_cmdtype[], char output_cmdparam[]) { //Set the percentage value of the stirrer
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CHPER_F(char output_cmdtype[], char output_cmdparam[]) { //Instructs the stirrer to turn on with the percentage specified
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CHIGH_F(char output_cmdtype[], char output_cmdparam[]) { //Requests the device to change the stepper motor to move the cup to the appropriate height
rtnProtocols(output_cmdtype, output_cmdparam);
}
void SHIGH_F(char output_cmdtype[], char output_cmdparam[]) { //Sets the given height to be the height the cup goes to during a test
rtnProtocols(output_cmdtype, output_cmdparam);
}
void MOTST_F(char output_cmdtype[], char output_cmdparam[]) { //Starts the cup motor to keep going up
rtnProtocols(output_cmdtype, output_cmdparam);
}
void MHIGH_F(char output_cmdtype[], char output_cmdparam[]) { //Notifies the machine that the top has been reached
rtnProtocols(output_cmdtype, output_cmdparam);
}
void MTRTT_F(char output_cmdtype[], char output_cmdparam[]) { //Notifies the amount of time that’s taken the machine to reach the top
rtnProtocols(output_cmdtype, output_cmdparam);
}
void RCTIC_F(char output_cmdtype[], char output_cmdparam[]) { //Resistance calibration test is being conducted, returns detected resistance from calibration test
long resistanceValue = strtol(output_cmdparam, NULL, 16);
for (int repeat = 0; repeat < 5; repeat++) {
// resistanceValue = random(resistanceValue * 0.98, resistanceValue * 1.02); //Scrambles the resistanceValue slightly by up to 2%
long long mCResistanceValue = random(1120, 1156) * resistanceValue / 1000 + random(23, 27);
ltoa(mCResistanceValue, output_cmdparam, 16);
//Serial.print("rV: ");
//Serial.println(resistanceValue);
// Serial.print("mCRV: ");
// Serial.println(mCResistanceValue);
// Serial.print("The pre-memmove o_c is: ");
// Serial.println(output_cmdparam);
int num_digits = log(mCResistanceValue) / log(16) + 1;
// Serial.print("num_digits: ");
// Serial.println(num_digits);
memmove(&(output_cmdparam[8 - num_digits]), &(output_cmdparam[0]), num_digits);
// Serial.print("The pre-0 o_c is: ");
// Serial.println(output_cmdparam);
for (int i = 1; i <= 8 - num_digits; i++)
output_cmdparam[i - 1] = '0';
strcpy(output_cmdtype, "RCTIC");
// Serial.print("The post-0 o_c is: ");
// Serial.println(output_cmdparam);
rtnProtocols(output_cmdtype, output_cmdparam);
delay(950);
}
}
void RCTGM_F(char output_cmdtype[], char output_cmdparam[]) { //Sends the resistance calibration m value
rtnProtocols(output_cmdtype, output_cmdparam);
//Don't think we need to process the data in actual.
}
void RCTGC_F(char output_cmdtype[], char output_cmdparam[]) { //Sends the resistance calibration c value
rtnProtocols(output_cmdtype, output_cmdparam);
}
void SAVEA_F(char output_cmdtype[], char output_cmdparam[]) { //Sends the introduced air volume
rtnProtocols(output_cmdtype, output_cmdparam);
}
void PREST_F(char output_cmdtype[], char output_cmdparam[]) { //Send method pre-sets
rtnProtocols(output_cmdtype, output_cmdparam);
}
void PREND_F(char output_cmdtype[], char output_cmdparam[]) { //End of method pre-sets
rtnProtocols(output_cmdtype, output_cmdparam);
}
void RQPRE_F(char output_cmdtype[], char output_cmdparam[]) { //Request device pre-sets
//char cmdparam[] = {output_cmdparam}; //Error is that char* shouldn't be converted to char. Why? Isn't cmdparam[] a char*
char cmdparam[9];
strcpy(cmdparam, output_cmdparam); //Saving the output_cmdparam for later use.
strcpy(output_cmdtype, "GVPRE");
strcpy(output_cmdparam, "01000000"); //cmdparam is config name
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "02952751"); //cmdparam is start temp
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "03012019"); //cmdparam is end temp
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "04043321"); //cmdparam is temp rate
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "05121212"); //cmdparam is ignition frequency
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "06888888"); //cmdparam is pressure threshold
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "ENPRE");
strcpy(output_cmdparam, cmdparam);
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CLPRE_F(char output_cmdtype[], char output_cmdparam[]) { //Delete all pre-sets on device
rtnProtocols(output_cmdtype, output_cmdparam);
}
void RQDAT_F(char output_cmdtype[], char output_cmdparam[]) { //Get results data
strcpy(output_cmdtype, "GVDAT");
strcpy(output_cmdparam, "01689689"); //A random output for date. CMBN, when the order itself is updated.
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "02777777"); //A random output for time
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "03198919"); //A random output for sample
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "04111111"); //A random output for method
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "05515151"); //A random output for flash
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "06141614"); //A random output for corrected flash
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "07070707"); //A random output for flashed?
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "08080808"); //A random output for start temp
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "09090909"); //A random output for temp rate
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "10101010"); //A random output for ignition frequency
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "11111111"); //A random output for pressure
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdparam, "12121212"); //A random output for pressure threshold
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "ENDAT");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CUPTC_F(char output_cmdtype[], char output_cmdparam[]) { //Get current cup temp
strcpy(output_cmdparam, "C1CAE148");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void LIDTC_F(char output_cmdtype[], char output_cmdparam[]) { //Get current lid temp
strcpy(output_cmdparam, "C1CAE148");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CURPR_F(char output_cmdtype[], char output_cmdparam[]) { //Get current pressure
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CUPTT_F(char output_cmdtype[], char output_cmdparam[]) { //Set cup temperature
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CDATE_F(char output_cmdtype[], char output_cmdparam[]) { //Receive the date
//rtnProtocols(output_cmdtype, output_cmdparam);
}
void CTIME_F(char output_cmdtype[], char output_cmdparam[]) { //Receive the date
//rtnProtocols(output_cmdtype, output_cmdparam);
}
void SDATE_F(char output_cmdtype[], char output_cmdparam[]) { //Receive the date
rtnProtocols(output_cmdtype, output_cmdparam);
}
void RDTTM_F(char output_cmdtype[], char output_cmdparam[]) { //Receive the date
strcpy(output_cmdtype, "CDATE");
strcpy(output_cmdparam, "30082022"); //30th Aug, 2022
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "CTIME");
strcpy(output_cmdparam, "15113800"); //15:11:38
rtnProtocols(output_cmdtype, output_cmdparam);
}
void SPROG_F(char output_cmdtype[], char output_cmdparam[]) { //Sets progress bar speed
rtnProtocols(output_cmdtype, output_cmdparam);
}
void SLOAD_F(char output_cmdtype[], char output_cmdparam[]) { //Sets loading circle speed
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CUFAC_F(char output_cmdtype[], char output_cmdparam[]) { //Factory reset the cup temperature calibration
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "CDATE");
strcpy(output_cmdparam, "30082022");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void LIFAC_F(char output_cmdtype[], char output_cmdparam[]) { //Factory reset the lid temperature calibration
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "CDATE");
strcpy(output_cmdparam, "30082022");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void STFAC_F(char output_cmdtype[], char output_cmdparam[]) { //Factory reset the stirrer calibration
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "CDATE");
strcpy(output_cmdparam, "30082022");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void MTFAC_F(char output_cmdtype[], char output_cmdparam[]) { //Factory reset the motor calibration
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "CDATE");
strcpy(output_cmdparam, "30082022");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void PPFAC_F(char output_cmdtype[], char output_cmdparam[]) { //Factory reset the pump calibration
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "CDATE");
strcpy(output_cmdparam, "30082022");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void PCOFF_F(char output_cmdtype[], char output_cmdparam[]) { //End any on-going process related to the desktop Software
rtnProtocols(output_cmdtype, output_cmdparam);
strcpy(output_cmdtype, "CNOFF");
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CUPFM_F(char output_cmdtype[], char output_cmdparam[]) { //Factory setting cup M
rtnProtocols(output_cmdtype, output_cmdparam);
}
void CUPFC_F(char output_cmdtype[], char output_cmdparam[]) { //Factory setting cup C
rtnProtocols(output_cmdtype, output_cmdparam);
}
void LIDFM_F(char output_cmdtype[], char output_cmdparam[]) { //Factory setting lid M
rtnProtocols(output_cmdtype, output_cmdparam);
}
void LIDFC_F(char output_cmdtype[], char output_cmdparam[]) { //Factory setting lid C
rtnProtocols(output_cmdtype, output_cmdparam);
}
void PREFC_F(char output_cmdtype[], char output_cmdparam[]) { //Factory setting pressure C
rtnProtocols(output_cmdtype, output_cmdparam);
}
void FCPWM_F(char output_cmdtype[], char output_cmdparam[]) { //Factory setting pump PWM
rtnProtocols(output_cmdtype, output_cmdparam);
}
void FCPER_F(char output_cmdtype[], char output_cmdparam[]) { //Factory setting stirrer percentage
rtnProtocols(output_cmdtype, output_cmdparam);
}
void FHIGH_F(char output_cmdtype[], char output_cmdparam[]) { //Factory setting motor height
rtnProtocols(output_cmdtype, output_cmdparam);
}
int checkSumGenerator(char message[]) {
int checkSum = 0;
for (int i = 0; i < 21; ++i) //Remove the Checksum character, as well as the Null Character
{
checkSum ^= message[i];
//Serial.println(message[i]);
}
return checkSum;
}
void rtnProtocols(char cmdtype[], char cmdparam[]) {
char outputString[28] = "TOWST_";
strcat (outputString, cmdtype);
strcat (outputString, "_");
strcat (outputString, cmdparam);
strcat (outputString, "_");
int outputCheckSum = checkSumGenerator(outputString);
char outputCheckSumHex[3] = "00"; //Receives data up to 255. And an extra line for '/0'.
itoa (outputCheckSum, outputCheckSumHex, 16); //Converts CheckSum to Hex. If value is under 16, char will only be in Hex[0].
if (outputCheckSum < 16) { //Adds a 0 if CS has fewer than 2 numbers
outputCheckSumHex[1] = outputCheckSumHex[0];
outputCheckSumHex[0] = '0';
}
outputCheckSumHex[0] = toupper (outputCheckSumHex[0]);
outputCheckSumHex[1] = toupper (outputCheckSumHex[1]);
//Serial.println(outputCheckSumHex);
strcat (outputString, outputCheckSumHex); //Now displayed in base16
outputString[23] = {'\r'}; //Not displayed in port. This should be happening, I think.
outputString[24] = {'\n'};
// for (int i = 0; i < strlen(outputString); i++) { //WST seems to have issues with taking CheckSum in lowercase
// outputString[i] = toupper (outputString[i]); //
// }
Serial.write(outputString);
//Serial.flush();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200); // usb port serial
pinMode(LED_BUILTIN, OUTPUT);
}
int msgReceiver(char endMarker, bool readyRead) {
char rc;
int ndx = 0;
while (readyRead == true) {
if (Serial.available() > 0) {
//Serial.println("In msgr.");
rc = Serial.read();
//Serial.print(rc);
//Serial.println("rc");
if (rc != endMarker) {
messageArray[ndx] = rc;
ndx++;
}
else if (rc == endMarker) {
messageArray[ndx] = '\0'; // terminate the string
//Serial.println("Received \n.");
rc = 0;
readyRead = false;
}
else {
readyRead = true;
}
}
}
return ndx;
}
void loop() {
//Collect data.
//char endMarker = '\n';
bool readyRead = true;
int i = 0;
//digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
//Serial.println("Serial available.");
if (Serial.available() > 0) {
//Serial.println("Serial available.");
i = msgReceiver('\n', readyRead); //msgReceiver is for turning the input to a char array. '\n' is end char. The output of msgReceiver is the char array position, so need to ++.
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //This turns an LED on and off.
messageArray[27] = '\0'; // terminate the string
int msgLength = i + 1;
//Serial.println(msgLength);
//Serial.println("Message received.");
for (i = msgLength; i > 22; i--) { //messageArray[22] is the 2nd char of the checkSum. Should not be ablated.
messageArray[i] = '\0';
}
bool canSend = true;
//Serial.println(messageArray);
//Serial.println(msgLength);
char checkSumCharacters[2] = {messageArray[i - 1], messageArray[i]}; //Values are ascii code of the base16 numbers.
int receivedCheckSum = strtoul(checkSumCharacters, NULL, 16); //Converts the base16 characters to an int.
int checkSum = checkSumGenerator(messageArray);
//Serial.println(checkSum);
for (i = 0; i < sizeof(cmdtarget); i++) { //Length of cmdtarget is 5.
cmdtarget[i] = messageArray[i];
// Serial.println(cmdtarget[i]);
// Serial.println(messageArray[i]);
}
cmdtarget[5] = '\0';
for (i = 0; i < sizeof(input_cmdtype) - 1; i++) { //Length of cmdtype is 5.
input_cmdtype[i] = messageArray[i + 6];
}
input_cmdtype[5] = '\0';
for (i = 0; i < sizeof(input_cmdparam) - 1; i++) { //Length of cmdparam is 8.
input_cmdparam[i] = messageArray[i + 12];
}
input_cmdparam[8] = '\0';
//Serial.println(cmdtarget);
//An attempt at a function pointer to be called for rtnProtocols. Pointer used to decrease negative effects of conditionals.
stringFunction *rtnpointer[] = {
FIRMV_F, VALCN_F, RQSPC_F, CTFTC_F, LIDVM_F, LIDVC_F, PREVC_F, STPWM_F, CHPWM_F, STPER_F, CHPER_F, CHIGH_F, SHIGH_F, MOTST_F, MHIGH_F, MTRTT_F,
RCTIC_F, RCTGM_F, RCTGC_F, SAVEA_F, PREST_F, PREND_F, RQPRE_F, CLPRE_F, RQDAT_F, CUPTC_F, LIDTC_F, CURPR_F, CUPTT_F, CDATE_F, CTIME_F, SDATE_F, RDTTM_F,
SPROG_F, SLOAD_F, CUFAC_F, LIFAC_F, STFAC_F, MTFAC_F, PPFAC_F, PCOFF_F, CUPFM_F, CUPFC_F, LIDFM_F, LIDFC_F, PREFC_F, FCPWM_F, FCPER_F, FHIGH_F,
};
input in = convert(input_cmdtype); //Using the char to enum converter.
canSend = errorStack(cmdtarget, receivedCheckSum, checkSum, msgLength, in, canSend);
if (canSend) {
char verak[6] = "VERAK";
rtnProtocols(verak, input_cmdparam);
//Serial.println(in);
rtnpointer[in](input_cmdtype, input_cmdparam);
}
}
}
bool errorStack(char cmdtarget[], int receivedCheckSum, int checkSum, int msgLength, input in, bool canSend) {
char output_cmdparam[9];
if (strcmp (cmdtarget, "TOWST") == 0) {
strcpy(output_cmdparam, "00000001");
canSend = false;
}
if (strcmp (cmdtarget, "TOWST") != 0 && strcmp (cmdtarget, "TOARM") != 0) {
strcpy(output_cmdparam, "00000002");
canSend = false;
}
if (receivedCheckSum != checkSum) {
strcpy(output_cmdparam, "00000005");
//Serial.println(checkSum);
//canSend = false;
}
if (msgLength < EXPECTED_MSGLENGTH) {
strcpy(output_cmdparam, "AAAAAA03");
canSend = false;
}
if (msgLength > EXPECTED_MSGLENGTH) {
strcpy(output_cmdparam, "AAAAAA04");
canSend = false;
}
//Need to determine data value
if (in == INVAL) {
strcpy(output_cmdparam, "00000007");
canSend = false;
}
if (canSend == false) {
char output_cmdtype[6] = "ERROR";
rtnProtocols(output_cmdtype, output_cmdparam);
}
return canSend;
}