Issue in uart communication

#include “mbed.h”
Serial uart4(PB_6, PA_10);
#define DEBUG 1 // change value to 1 to enable debuging using serial monitor
//---------for delay----------------------------------------------
unsigned long previousTime = 0;

//-------CO2 Variable and calibration command, co2 concentration declaration.----------------------------------#define INTERVAL 5000
unsigned int response [9];
int packetlenght =9;

typedef unsigned char byte;
const byte *mhzResp[9]; // 9 bytes bytes response
const byte mhzCmdCalibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
const byte mhzCmdABCEnable[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
const byte mhzCmdABCDisable[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
const byte mhzCmdMeasurementRange5000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0xCB};

int shifts=0,co2ppm;

long previousMillis = 0;
unsigned int checksum (unsigned int response[9]){
unsigned int crc = 0;
for (int i = 1; i < 8; i++) {
crc += response[i];
}
crc = 255 - crc + 1;
return crc;
}
void disableABC() {
uart4.write(mhzCmdABCDisable, 9, false);
}

void enableABC() {
uart4.write(mhzCmdABCEnable, 9, false);
}

void setRange5000() {
uart4.write(mhzCmdMeasurementRange5000, 9, false);
}
void calibrateZero(){
uart4.write(mhzCmdCalibrateZero, 9, false);
}

int readCO2() {
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
uart4.write(cmd, 9, false);
while(uart4.readable()) {
uart4.getc();
shifts++;
}
memset(response, 0, 9);
uart4.putc(packetlenght[response]);

for (int i=0; i<9; i++) {
//Serial.print(" 0x");
//Serial.print(response[i], HEX);
}
if (response[1] != 0x86)
{
printf(" Invalid response from co2 sensor! \n\r");
return -1;
}
if (response[8] == checksum(response)) {
int responseHigh = (int) response[2];
int responseLow = (int) response[3];
int ppm = (256 * responseHigh) + responseLow;
return ppm;
} else
{
printf(“CRC error!\n\r”);
return -1;
}
}
//----------------Timers auxiliar variables--------------------
Timer timer;
long now = timer.read_ms();
long lastMeasure = 0;
DigitalOut myled(LED1);

int main() {
uart4.baud(9600); // Setting baud rate to 9600
int i = 1;
printf(“Hello World !”);
while(1) {
wait(1);
unsigned long currentMillis = now;
if (co2ppm > 10000) {
printf(“Zero was calibrated \n\r”);
// disableABC();
wait(1800000);
//calibrateZero();
enableABC();
}
else if ((currentMillis - previousMillis) > INTERVAL) {
previousMillis = currentMillis;
co2ppm=-999;
co2ppm = readCO2();
}
printf(“CO2= %d.\n\r”, co2ppm);
i++;
myled = !myled;
}
}
here i am interfacing the mhz-14a co2 sensor with nucleo L152re board and co2 sensor is working on uart communication, this code is error free and gives the co2 value is 0 in all time.please help me where is problem in my code as soon as possible.

Ahoj,

I do not understand why you create a new topic for same thing with same bad description again.
Why you want help from people when you not want listen?

Correct formatting for better reading

#include “mbed.h”
Serial uart4(PB_6, PA_10);
#define DEBUG 1 // change value to 1 to enable debuging using serial monitor
//---------for delay----------------------------------------------
unsigned long previousTime = 0;

//-------CO2 Variable and calibration command, co2 concentration declaration.----------------------------------#define INTERVAL 5000
unsigned int response [9];
int packetlenght =9;

typedef unsigned char byte;
const byte *mhzResp[9]; // 9 bytes bytes response
const byte mhzCmdCalibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
const byte mhzCmdABCEnable[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
const byte mhzCmdABCDisable[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
const byte mhzCmdMeasurementRange5000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0xCB};

int shifts=0,co2ppm;
long previousMillis = 0;

unsigned int checksum (unsigned int response[9]){
    unsigned int crc = 0;
    for (int i = 1; i < 8; i++) {
        crc += response[i];
    }
    crc = 255 - crc + 1;
    return crc;
}

void disableABC() {
    uart4.write(mhzCmdABCDisable, 9, false);
}

void enableABC() {
    uart4.write(mhzCmdABCEnable, 9, false);
}

void setRange5000() {
    uart4.write(mhzCmdMeasurementRange5000, 9, false);
}
void calibrateZero(){
    uart4.write(mhzCmdCalibrateZero, 9, false);
}

int readCO2() {
    byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
    uart4.write(cmd, 9, false);
    while(uart4.readable()) {
        uart4.getc();
        shifts++;
    }
    memset(response, 0, 9);
    uart4.putc(packetlenght[response]);

    for (int i=0; i<9; i++) {
    //Serial.print(" 0x");
    //Serial.print(response[i], HEX);
    }
    if (response[1] != 0x86){
        printf(" Invalid response from co2 sensor! \n\r");
        return -1;
    }
    if (response[8] == checksum(response)) {
        int responseHigh = (int) response[2];
        int responseLow = (int) response[3];
        int ppm = (256 * responseHigh) + responseLow;
        return ppm;
    }else{
        printf(“CRC error!\n\r”);
    return -1;
}
}
//----------------Timers auxiliar variables--------------------
Timer timer;
long now = timer.read_ms();
long lastMeasure = 0;
DigitalOut myled(LED1);

int main() {
    uart4.baud(9600); // Setting baud rate to 9600
    int i = 1;
    printf(“Hello World !”);
    while(1) {
        wait(1);
        unsigned long currentMillis = now;
        if (co2ppm > 10000) {
            printf(“Zero was calibrated \n\r”);
            // disableABC();
            wait(1800000);
            //calibrateZero();
            enableABC();
        }
        else if ((currentMillis - previousMillis) > INTERVAL) {
            previousMillis = currentMillis;
            co2ppm=-999;
            co2ppm = readCO2();
        }
        printf(“CO2= %d.\n\r”, co2ppm);
        i++;
        myled = !myled;
    }
}

I can not test your code because I do not have this sensor but I check the main and the problem is the timer, I think.
You have declaration & initialization of a variable now = timer.read_ms(); but from my point of view you need to have it inside the loop. Because otherwise your currentMillis is always same value what was measured before entering the main function.
So you need to change it to something liek this.

//----------------Timers auxiliar variables--------------------
Timer timer;
//long now = timer.read_ms();
long lastMeasure = 0;
DigitalOut myled(LED1);

int main() {
    uart4.baud(9600); // Setting baud rate to 9600
    int i = 1;
    printf(“Hello World !”);
	/*-Starting the timer-*/
	timer.start();
	/*------------------------*/
    while(1) {
        wait(1);
		//unsigned long currentMillis = now;
		/*-Read the timer in every loop-*/
		unsigned long currentMillis = timer.read_ms();
		/*------------------------*/
        if (co2ppm > 10000) {
            printf(“Zero was calibrated \n\r”);
            // disableABC();
            wait(1800000);
            //calibrateZero();
            enableABC();
        }else if ((currentMillis - previousMillis) > INTERVAL) {
            previousMillis = currentMillis;
            co2ppm=-999;
            co2ppm = readCO2();
        }
        printf(“CO2= %d.\n\r”, co2ppm);
        i++;
        myled = !myled;
	}
}

I hope that will help you.

BTW I recommend to use printf for debugging the status of your conditions.

BR, Jan

When i use your correct code then output shows the error is given below.

Invalid response from co2 sensor!
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
Invalid response from co2 sensor!
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
Invalid response from co2 sensor!
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.

I told you use the printf for debugging…
You need to check your read function, something is missing here.
I am sure that is not correct

    while(uart4.readable()) {
        uart4.getc();
        shifts++;
    }

Must be something like that

    while(uart4.readable()) {
        char c = uart4.getc(); // then put the c variable to a buffer
        buffer[shifts++] = c;
    }

BR, Jan

Ok sir, as you told i did all these things code then below is modified code. but gives an error. And checking the uart communication is working with TTL.

#include “mbed.h”
Serial uart4(PB_6, PA_10);
#define DEBUG 1 // change value to 1 to enable debuging using serial monitor
//---------for delay----------------------------------------------
unsigned long previousTime = 0;

//-------CO2 Variable and calibration command, co2 concentration declaration.-----------------------------------
#define INTERVAL 5000
unsigned int response [9];
int packetlenght =9;

typedef unsigned char byte;
const byte *mhzResp[9]; // 9 bytes bytes response
const byte mhzCmdCalibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
const byte mhzCmdABCEnable[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
const byte mhzCmdABCDisable[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
const byte mhzCmdMeasurementRange5000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0xCB};

int shifts=0,co2ppm;
char buffer[1023];
char c;

long previousMillis = 0;
unsigned int checksum (unsigned int response[9]){
unsigned int crc = 0;
for (int i = 1; i < 8; i++) {
crc += response[i];
}
crc = 255 - crc + 1;
return crc;
}

void disableABC() {
uart4.write(mhzCmdABCDisable, 9, false);
}

void enableABC() {
uart4.write(mhzCmdABCEnable, 9, false);
}

void setRange5000() {
uart4.write(mhzCmdMeasurementRange5000, 9, false);
}

void calibrateZero(){
uart4.write(mhzCmdCalibrateZero, 9, false);
}

int readCO2() {
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
uart4.write(cmd, 9, false);
// The serial stream can get out of sync. The response starts with 0xff, try to resync.
// while(uart4.readable()) {
// uart4.getc();
// shifts++;
// }
while(uart4.readable()) {
char c = uart4.getc(); // then put the c variable to a buffer
buffer[c++];
}
memset(response, 0, 9);
uart4.putc(packetlenght[response]);

//for (int i=0; i<9; i++) {
// printf(" 0x");
// printf(“%02hhx”,response[i]);
//}
//printf(" Response OK. Shifts="+String(c));

if (response[1] != 0x86)
{
printf(" Invalid response from co2 sensor! \n\r");
return -1;
}

if (response[8] == checksum(response)) {
int responseHigh = (int) response[2];
int responseLow = (int) response[3];
int ppm = (256 * responseHigh) + responseLow;
return ppm;
// printf(“CO2= %d.\n\r”, ppm);
} else
{
printf(“CRC error!\n\r”);
return -1;
}
}
//----------------Timers auxiliar variables--------------------
Timer timer;
//long now = timer.read_ms();
long lastMeasure = 0;
DigitalOut myled(LED1);

int main() {
uart4.baud(9600); // Setting baud rate to 9600
int i = 1;
printf(“Hello World !”);
/-Starting the timer-/
timer.start();
/------------------------/
while(1) {
wait(1);
//unsigned long currentMillis = now;
/-Read the timer in every loop-/
unsigned long currentMillis = timer.read_ms();
/------------------------/
if (co2ppm > 10000) {
printf(“Zero was calibrated \n\r”);
// disableABC();
wait(1800000);
//calibrateZero();
enableABC();
}else if ((currentMillis - previousMillis) > INTERVAL) {
previousMillis = currentMillis;
co2ppm=-999;
co2ppm = readCO2();
}
printf(“CO2= %d.\n\r”, co2ppm);
i++;
myled = !myled;
}
}
And print this error–
Invalid response from co2 sensor!
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
Invalid response from co2 sensor!
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.

It can not work because you do not understand it.
You need to understand to basics before you can to do something.

The while loop has same effect like before because you not use your buffer response.
And the third time, please be so kind and use these symbols ``` before and after your code.

#include “mbed.h”
Serial uart4(PB_6, PA_10);
#define DEBUG 1 // change value to 1 to enable debuging using serial monitor
//---------for delay----------------------------------------------
unsigned long previousTime = 0;

//-------CO2 Variable and calibration command, co2 concentration declaration.-----------------------------------
#define INTERVAL 5000
unsigned int response [9];
int packetlenght = 9;

typedef unsigned char byte;
const byte *mhzResp[9]; // 9 bytes bytes response /*NEVER USED*/
const byte mhzCmdCalibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
const byte mhzCmdABCEnable[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
const byte mhzCmdABCDisable[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
const byte mhzCmdMeasurementRange5000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0xCB};

int shifts=0 /*NEVER USED*/,co2ppm;

/* THIS IS NOT NECESSARY*/
//char buffer[1023];
//char c; 


long previousMillis = 0;
unsigned int checksum (unsigned int response[9]){
	unsigned int crc = 0;
	for (int i = 1; i < 8; i++) {
		crc += response[i];
	}
	crc = 255 - crc + 1;
	return crc;
}

void disableABC() {
	uart4.write(mhzCmdABCDisable, 9, false);
}

void enableABC() {
	uart4.write(mhzCmdABCEnable, 9, false);
}

void setRange5000() {
	uart4.write(mhzCmdMeasurementRange5000, 9, false);
}

void calibrateZero(){
	uart4.write(mhzCmdCalibrateZero, 9, false);
}

int readCO2() {
	byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
	uart4.write(cmd, 9, false);
	
	memset(response, 0, 9); 				// fill array with zeros
	int counter = 0;						// a counter
	while(uart4.readable()) {				// if a byte is available
		char c = uart4.getc(); 				// get one char from stream
		response[counter++] = c;		 	// put the char to your buffer 'response' and increment counter for next char
	}
	printf("Response is: %s\n", response);	// print the response to the console
	
	/*??? I do not understand what you mean with that*/
	//uart4.putc(packetlenght[response]); 


	if (response[1] != 0x86){
		printf(" Invalid response from co2 sensor! \n\r");
		return -1;
	}else{
		if (response[8] == checksum(response)) {
			int responseHigh = (int) response[2];
			int responseLow = (int) response[3];
			int ppm = (256 * responseHigh) + responseLow;
			return ppm;
			// printf(“CO2= %d.\n\r”, ppm);
		} else {
			printf(“CRC error!\n\r”);
			return -1;
		}
	}
}

//----------------Timers auxiliar variables--------------------
Timer timer;
//long now = timer.read_ms();
long lastMeasure = 0;
DigitalOut myled(LED1);

int main() {
	uart4.baud(9600); // Setting baud rate to 9600
	int i = 1;
	printf(“Hello World !”);
	/-Starting the timer-/
	timer.start();
	/------------------------/
	while(1) {
	wait(1);
		//unsigned long currentMillis = now;
		/-Read the timer in every loop-/
		unsigned long currentMillis = timer.read_ms();
		/------------------------/
		if (co2ppm > 10000) {
			printf(“Zero was calibrated \n\r”);
			// disableABC();
			wait(1800000);
			//calibrateZero();
			enableABC();
		}else if ((currentMillis - previousMillis) > INTERVAL) {
			previousMillis = currentMillis;
			co2ppm=-999;
			co2ppm = readCO2();
		}
		printf(“CO2= %d.\n\r”, co2ppm);
		i++;
		myled = !myled;
	}
}

BR, Jan

Sorry sir, actually i am a beginner for stm32 controller and mbed ide so i am phasing these problem.
And code id error and and give some response value and print invalid response look like this:
Response is: 536871588
Invalid response from co2 sensor!
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.
CO2= -1.

Hello friend,

I not forgot on you

Ok, above was a data type collision probably, nwm.

Anyway I made an investigation and I think the while loop can miss the data from sensor because it can be much faster than the response from sensor and pauses between bytes.
I made a piece of code, see below. Of course I can not say “it will working” because I have no sensor for testing but maybe it will help you with your journey.

#include "mbed.h"
#define SIZE 9
Serial sensor(PB_6, PA_10);
DigitalOut led(LED1);
Timer timer;

int main(){
    printf("Exmaple start\n");
    char getGasCmd[SIZE] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
    char response[SIZE+1];  // buffer
    
    timer.start();
    while(1){
        int currentTime = timer.read_ms();
        if(currentTime >= 5000){
            printf("Send read CMD\n");
            memset(response, NULL, SIZE+1);         // clear the response buffer
            for(int i = 0; i < SIZE; i++){          // send 9 bytes of the command
                sensor.putc(getGasCmd[i]);
            } 
            
            int i_buffer = 0;
            bool timeOut = false;
            //char c = 0xff;
            timer.reset();                          // restart timer for loop timeout
            while(1){
                if(sensor.readable()){
                    /*c = sensor.getc();         
                    if(c == '\n'){                  
                        break;
                    }else{
                        response[i_buffer] = c;
                        i_buffer++;
                    }*/
                    response[i_buffer] = sensor.getc();
                    i_buffer++;
                    if(i_buffer == 9) break;
                }else{
                    if(timer.read_ms() > 3000){      // brake loop after timeout
                        timeOut = true;
                        break;
                    }
                }
            }
            if(timeOut){
                printf("Time out 3sec - %d bytes\n\r", i_buffer);    
            }else{
                //printf("Response: %s\n", response);
                if (i_buffer != SIZE){
                    printf(" Invalid response  - %d bytes\n\r", i_buffer);
                }else{
                    if (response[1] != 0x86){
                        printf(" Invalid response from co2 sensor! \n\r");
                    }else{
                        int ppm = (256 * (int)response[2]) + (int)response[3];
                        printf("CO2= %d.\n\r", ppm);
                    }
                }
            }
            timer.reset();
         }else{
            led = !led;
            wait(1);
         }
    }
}

Let me know or questions.

BR, Jan

it gives the output below. And code is error free.
Exmaple start
Send read CMD
Time out 3sec - 9 bytes
Send read CMD
Time out 3sec - 9 bytes
Send read CMD
Time outTime out 3sec - 9 bytes
Send read CMD
Time out 3sec - 9 bytes
Send read CMD
Time out 3sec - 9 bytes

Hi,

ok, so now we know we really have a response from the sensor, that is good I think.
I modified my code above and cut out the if statement with the \n.
Please be so kind and try it again.

BR, Jan