Hello! I am trying to send some strings in raw binary from the computer to arduino nano using serial communication. On the PC side, I am using a c library "libserialport" from sigrokproject to manage the serial communication. I could have used linux termios but it is too low level for me. The problem is arduino reads incorrect values of bytes, when i send them from pc. I used start and stop markers to send the packets, but still no effect. What am i doing wrong pls help...
My PC program:
#include <libserialport.h>
#include <inttypes.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define ID_STORE 1
#define ID_RETRIEVE 2
#define GENDER_STORE 3
#define GENDER_RETRIEVE 4
#define NAME_STORE 5
#define NAME_RETRIEVE 6
#define OK 10
#define NOT_OK 11
uint8_t recv_buf[50];
static int get_msg_len(char *msg)
{
int len = 0;
while (msg[len] != '\n') {
len++;
}
return len+1;
}
static struct sp_port *port_init(char *name)
{
struct sp_port *port;
sp_get_port_by_name(name, &port);
sp_open(port, SP_MODE_READ_WRITE);
sleep(3);
sp_set_baudrate(port, 9600);
sp_set_bits(port, 8);
sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE);
sp_set_parity(port, SP_PARITY_NONE);
sp_set_stopbits(port, 1);
sp_flush(port, SP_BUF_BOTH);
return port;
}
static void port_exit(struct sp_port *port)
{
sp_free_port(port);
sp_close(port);
}
static int port_start_transmission(struct sp_port *port, uint8_t mode)
{
uint8_t sop = '<', eop = '>';
while (sp_output_waiting(port) > 0) usleep(2);
sp_nonblocking_write(port, &sop, sizeof(sop));
while (sp_output_waiting(port) > 0) usleep(2);
sp_nonblocking_write(port, &mode, sizeof(mode));
while (sp_output_waiting(port) > 0) usleep(2);
sp_nonblocking_write(port, &eop, sizeof(eop));
while (sp_output_waiting(port) > 0) usleep(2);
sp_drain(port);
uint8_t response[8];
int done = 0;
int inc = 0;
int start = 0;
while (!done) {
if (sp_input_waiting(port) > 0) {
uint8_t byte;
sp_nonblocking_read(port, &byte, sizeof(byte));
if (byte == sop) {
start = 1;
continue;
} else if (byte == eop) {
done = 1;
continue;
}
if (start) {
response[inc++] = byte;
}
}
usleep(2);
}
return response[0];
}
static int port_send_msg(struct sp_port *port, char *msg, int msg_len, uint8_t mode)
{
uint8_t sop = '<', eop = '>';
msg[msg_len - 1] = '\0';
int response = port_start_transmission(port, mode);
if (response == OK) {
int inc = 0;
sp_nonblocking_write(port, &sop, sizeof(sop));
while (msg_len) {
sp_nonblocking_write(port, &msg[inc++], sizeof(msg[0]));
while (sp_output_waiting(port) > 0) usleep(2);
msg_len--;
}
sp_nonblocking_write(port, &eop, sizeof(eop));
while (sp_output_waiting(port) > 0) usleep(2);
return 1;
} else if (response == NOT_OK) {
return 0;
}
return 0;
}
static int port_receive_msg(struct sp_port *port, uint8_t mode)
{
uint8_t sop = '<', eop = '>';
int response = port_start_transmission(port, mode);
if (response == OK) {
int done = 0;
int inc = 0;
int start = 0;
while (!done) {
if (sp_input_waiting(port) > 0) {
uint8_t byte;
sp_nonblocking_read(port, &byte, sizeof(byte));
if (byte == sop) {
start = 1;
continue;
} else if (byte == eop) {
done = 1;
continue;
}
if (start) {
recv_buf[inc++] = byte;
}
}
usleep(2);
}
return 1;
} else if (response == NOT_OK) {
return 0;
}
return 0;
}
static void interface_store(struct sp_port *port)
{
int running = 1;
while (running)
{
printf("1. Store name?\n"
"2. Store id?\n"
"3. Store gender?\n"
"4. Go to main menu?\n\n"
);
printf("Enter a number: ");
fflush(stdout);
int num;
scanf("%d", &num);
getchar();
printf("\n");
char buf[50];
int code;
switch (num)
{
case 1:
printf("Enter your name: \n");
fgets(buf, sizeof(buf), stdin);
printf("Sending info...\n");
code = port_send_msg(port, buf, get_msg_len(buf), NAME_STORE);
if (code)
printf("Sent successfully! Press enter to continue...");
else {
printf("Sent unsuccessful:( Press enter to continue...");
}
fflush(stdout);
getchar();
system("clear");
running = 1;
break;
case 2:
printf("Enter your id: \n");
fgets(buf, sizeof(buf), stdin);
printf("Sending info...\n");
code = port_send_msg(port, buf, get_msg_len(buf), ID_STORE);
if (code)
printf("Sent successfully! Press enter to continue...");
else {
printf("Sent unsuccessful:( Press enter to continue...");
}
fflush(stdout);
getchar();
system("clear");
running = 1;
break;
case 3:
printf("Enter your gender: \n");
fgets(buf, sizeof(buf), stdin);
printf("Sending info...\n");
code = port_send_msg(port, buf, get_msg_len(buf), GENDER_STORE);
if (code)
printf("Sent successfully! Press enter to continue...");
else {
printf("Operation unsuccessful:( Press enter to continue...");
}
fflush(stdout);
getchar();
system("clear");
running = 1;
break;
case 4:
running = 0;
break;
default:
printf("Invalid number! Press enter to continue...");
fflush(stdout);
getchar();
system("clear");
running = 1;
break;
}
}
}
static void interface_retrieve(struct sp_port *port)
{
int running = 1;
while (running) {
printf("1. Retrieve name?\n"
"2. Retrieve id?\n"
"3. Retrieve gender?\n"
"4. Go to main menu?\n\n"
);
printf("Enter a number: ");
fflush(stdout);
int num;
scanf("%d", &num);
getchar();
printf("\n");
int code;
switch (num)
{
case 1:
printf("Retrieving info...\n");
code = port_receive_msg(port, NAME_RETRIEVE);
if (code)
printf("Device owner name is: %s. Press enter to continue...", recv_buf);
else {
printf("Operation unsuccessful:( Press enter to continue...");
}
fflush(stdout);
getchar();
system("clear");
running = 1;
break;
case 2:
printf("Retrieving info...\n");
code = port_receive_msg(port, ID_RETRIEVE);
if (code)
printf("Device owner name is: %s. Press enter to continue...", recv_buf);
else {
printf("Operation unsuccessful:( Press enter to continue...");
}
fflush(stdout);
getchar();
system("clear");
running = 1;
break;
case 3:
printf("Retrieving info...\n");
code = port_receive_msg(port, GENDER_RETRIEVE);
if (code)
printf("Device owner name is: %s. Press enter to continue...", recv_buf);
else {
printf("Operation unsuccessful:( Press enter to continue...");
}
fflush(stdout);
getchar();
system("clear");
running = 1;
break;
case 4:
running = 0;
break;
default:
printf("Invalid number! Press enter to continue...");
fflush(stdout);
getchar();
system("clear");
running = 1;
break;
}
}
}
static int interface_main(struct sp_port *port)
{
printf("1. Store operation?\n"
"2. Retrieve operation?\n"
"3. Exit?\n\n"
);
printf("Enter a number: ");
fflush(stdout);
int num;
scanf("%d", &num);
getchar();
printf("\n\n");
switch (num)
{
case 1:
system("clear");
interface_store(port);
system("clear");
return 1;
case 2:
system("clear");
interface_retrieve(port);
system("clear");
return 1;
case 3:
return 0;
default:
printf("Invalid number! Press enter to continue...");
fflush(stdout);
getchar();
system("clear");
return 1;
}
}
static void main_loop()
{
int running = 1;
struct sp_port *port = port_init("/dev/ttyUSB0");
while(running) {
running = interface_main(port);
}
port_exit(port);
}
int main(int argc, char **argv)
{
// Starting point. Process events, shows interface. Can run forever if no exit msg received from user.
main_loop();
return 0;
}
The code running on Arduino:
#define ID_STORE 1
#define ID_RETRIEVE 2
#define GENDER_STORE 3
#define GENDER_RETRIEVE 4
#define NAME_STORE 5
#define NAME_RETRIEVE 6
#define OK 1
#define NOT_OK 0
byte id[50];
byte gender[50];
byte name[50];
byte buf[50];
int get_len(byte *msg) {
int len = 0;
while (msg[len] != '\0') {
len++;
}
return len + 1;
}
int confirm_transmission() {
byte sop = '<', eop = '>';
int done = 0;
int inc = 0;
int start = 0;
byte response[8];
memset(response, 0, sizeof(response));
while (!done) {
if (Serial.available() > 0) {
byte val = Serial.read();
digitalWrite(LED_BUILTIN, HIGH);
if (val == sop) {
start = 1;
continue;
} else if (val == eop) {
done = 1;
continue;
}
if (start) {
response[inc++] = val;
}
}
}
if (response[0] == 0) {
while (Serial.availableForWrite() <= 0);
Serial.write(sop);
while (Serial.availableForWrite() <= 0);
Serial.write(NOT_OK);
while (Serial.availableForWrite() <= 0);
Serial.write(eop);
while (1);
} else {
while (Serial.availableForWrite() <= 0);
Serial.write(sop);
while (Serial.availableForWrite() <= 0);
Serial.write(OK);
while (Serial.availableForWrite() <= 0);
Serial.write(eop);
return response[0];
}
}
void send_msg(byte *msg) {
byte sop = '<', eop = '>';
while (Serial.availableForWrite() <= 0);
Serial.write(sop);
int len = get_len(msg);
int inc = 0;
while (len) {
while (Serial.availableForWrite() <= 0);
Serial.write(msg[inc++]);
len--;
}
while (Serial.availableForWrite() <= 0);
Serial.write(eop);
}
void recv_msg() {
byte sop = '<', eop = '>';
int done = 0;
int inc = 0;
int start = 0;
while (!done) {
if (Serial.available() > 0) {
byte val = Serial.read();
if (val == sop) {
start = 1;
continue;
} else if (val == eop) {
done = 1;
continue;
}
if (start) {
buf[inc++] = val;
}
}
}
}
void fill_id(byte *msg) {
int inc = 0;
while (msg[inc] != '\0') {
id[inc] = msg[inc];
inc++;
}
id[inc] = '\0';
}
void fill_gender(byte *msg) {
int inc = 0;
while (msg[inc] != '\0') {
gender[inc] = msg[inc];
inc++;
}
gender[inc] = '\0';
}
void fill_name(byte *msg) {
int inc = 0;
while (msg[inc] != '\0') {
name[inc] = msg[inc];
inc++;
}
name[inc] = '\0';
}
void setup() {
Serial.begin(1200);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
int mode = confirm_transmission();
switch (mode) {
case ID_STORE:
recv_msg();
fill_id(buf);
break;
case GENDER_STORE:
recv_msg();
fill_gender(buf);
break;
case NAME_STORE:
recv_msg();
fill_name(buf);
break;
case ID_RETRIEVE:
send_msg(id);
break;
case GENDER_RETRIEVE:
send_msg(gender);
break;
case NAME_RETRIEVE:
send_msg(name);
break;
default:
break;
}
}