CAN identifier message sync issue - c++

I am struggling with a CAN code. with Arduino I am sending two signals with 2 different identifiers and my code checks the identifier id and then interprets the message as eithr state-of-charge or a Voltage message. The code works fine with a single SOC or volt message.
The problem im getting is that when there are multiple message, the code reads the identifier once and then reads all messages given. This means, it reads id 0x140, then reads all signals even the ones that are associated with other ids.
I don't know if its problem with my code or have to activate some flags or something.
//WORKS FINE FOR A SINGLE CAN MESSAGE, BUT HAVE ID - MESSAGE SYN ISSUES
//WITH MULTIPLE MESSAGES//
#include "pin_info.h"
#include <stdio.h>
#include <stdlib.h>
#include <Time.h>
#include <SPI.h> //for CAN
#include "mcp_can.h"
//#include "canLib.h"
#include "FreeMono9pt7b.h"
const int spiCSPin = 3;
MCP_CAN CAN(spiCSPin);
unsigned char len = 0;
unsigned char temp_buf[8];
unsigned char soc_buf[8]={0};
unsigned char volt_buf[8]={0};
unsigned char soc_mean[2], soc_min[2], soc_max[2] ={0,0};
float s_mean, s_min, s_max;
unsigned char volt_mean[2], volt_max[2], volt_min[2]= {0,0};
float v_mean, v_min, v_max;
int len_= sizeof(soc_mean);
const char Message[]= "CAN Message: " ;
const char Name[]= "foxBMS";
//enum type{soc,SOC, volt, VOLT};
void setup()
{
/*FOR CAN*/
Serial.begin(115200);
pinMode(LED_BUILTIN,OUTPUT);
while (CAN_OK != CAN.begin(CAN_500KBPS))
{
Serial.println("CAN BUS Init Failed");
delay(100);
}
Serial.println("CAN BUS Init OK!");
/* set mask, set both the mask to 0x3ff*/
CAN.init_Mask(0, 0, 0x3ff); // there are 2 mask in mcp2515, you need to set both of them
CAN.init_Mask(1, 0, 0x3ff);
/*set filter, we can receive id from 0x140 & 0x170 */
CAN.init_Filt(0, 0, 0x140); // there are 6 filter in mcp2515
CAN.init_Filt(1, 0, 0x170); // there are 6 filter in mcp2515
}
void loop()
{
if(CAN_MSGAVAIL == CAN.checkReceive())
{
unsigned long canId = CAN.getCanId();
CAN.readMsgBuf(&len, temp_buf);
assign(temp_buf,canId);
serialDisplay(canId);
//CAN.checkClearRxStatus(temp_buf);
CAN.clearBufferTransmitIfFlags();
}
else
{ Serial.print("No message received \n");
}
}
void assign(unsigned char buf[], unsigned long id)
{
if(id==0x00)
{}
else if(id==0x140)
{
for (int i=0; i<len; i++)
{
if (i<2)
soc_mean[i]= buf[i];
else if (i<4 && i>=2)
soc_min[i-2]= buf[i];
else if (i<6 && i>=4)
soc_max[i-4]= buf[i];
}
}
else if(id==0x170)
{
for (int i=0; i<len; i++)
{
if (i<2)
volt_mean[i]= buf[i];
else if (i<4 && i>=2)
volt_min[i-2]= buf[i];
else if (i<6 && i>=4)
volt_max[i-4]= buf[i];
}
}
}
void serialDisplay(unsigned long id)
{
Serial.println("-----------------------------");
Serial.print("Data from ID: ");
Serial.print(id,HEX); Serial.println("- CAN0_MSG");
for(int i = 0; i<len; i++)
{
Serial.print(temp_buf[i], HEX); Serial.print("\t");
}
Serial.print("\n");
}

Related

Cannot send serial data from raspberry pi pico ( c sdk )

I'm making a remote controlled machine using a pi pico to drive the motors and read some sensors, and a raspberry pi 4 to send commands to the pi pico via serial and host the web interface.
I am currently testing the operation of the serial from the pi pico. To do this I have connected the pi pico with the raspberry in the following way:
Currently, I am using the following files:
1. main.c to receive and send
2. ring_queue.h where the code for the ring queue is located
main.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/irq.h"
#include "ring_queue.h"
#define UART_ID uart0
#define BAUD_RATE 115200
#define DATA_BITS 8
#define STOP_BITS 1
#define PARITY UART_PARITY_NONE
#define UART_TX_PIN 0
#define UART_RX_PIN 1
#define LED_PIN PICO_DEFAULT_LED_PIN
volatile int chars_rxed = 0;
volatile char uCommand[32];
volatile queue *rx_queue;
volatile queue *tx_queue;
void receive_rx(){
while(uart_is_readable(UART_ID)){
char ch = uart_getc(UART_ID);
printf("Got a ch! %c\n", ch);
if(ch != 10){
uCommand[chars_rxed] = ch;
}
printf("Should have added it to uCommand: %s\n", uCommand);
if(uCommand[chars_rxed] == '/'){
printf("End of the command\n");
queue_enqueue((queue*)rx_queue, (char*)uCommand);
memset((char*)uCommand, 0, sizeof(uCommand));
chars_rxed = 0;
break;
}
if(ch != 10) chars_rxed++;
}
}
void send_tx(){
if(queue_empty((queue*)tx_queue) == 1){
return;
}
else{
printf("Trying to send something\n");
char *foo = queue_dequeue((queue*)tx_queue);
uart_write_blocking(UART_ID, (char*)foo, 32);
//printf("%s\n", queue_dequeue((queue*)tx_queue));
}
}
int main(){
stdio_init_all();
memset((char*)uCommand, 0, sizeof(uCommand));
rx_queue = create_queue(32);
tx_queue = create_queue(32);
uart_init(UART_ID, BAUD_RATE);
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
uart_set_hw_flow(UART_ID, false, false);
uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY);
uart_set_fifo_enabled(UART_ID, true);
int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ;
irq_set_exclusive_handler(UART_IRQ, receive_rx);
irq_set_enabled(UART_IRQ, true);
uart_set_irq_enables(UART_ID, true, false);
while (1){
tight_loop_contents();
if(queue_size((queue*)rx_queue) != 0){
printf("Moving from rx to tx to print the received command\n");
queue_enqueue((queue*)tx_queue, queue_dequeue((queue*)rx_queue));
}
send_tx();
}
}
ring_queue.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
unsigned int tail; // current tail
unsigned int head; // current head
unsigned int size; // current number of items
unsigned int capacity; // Capacity of queue
char** data; // Pointer to array of data
} queue;
queue *create_queue(unsigned int _capacity){
printf("Malloc!\n");
queue *myQueue = malloc(sizeof(queue));
printf("Malloc done!\n");
if (myQueue == NULL ){
printf("Malloc failed!\n");
return NULL;
}
else {
printf("Malloc succeed!\n");
myQueue->tail = -1;
myQueue->head = 0;
myQueue->size = 0;
myQueue->capacity = _capacity;
myQueue->data = malloc(_capacity * sizeof(char*));
return myQueue;
}
}
int queue_empty(queue *q) {
if(q == NULL) return -1;
else if(q->size == 0) return 1;
else return 0;
}
int queue_full(queue *q) {
if(q == NULL) return -1;
else if(q->size == q->capacity) return 1;
else return 0;
}
int queue_enqueue(queue *q, const char *item) {
if (q == NULL) return -1;
else if (queue_full(q) == 1) return 0;
else {
q->tail = (q->tail + 1) % q->capacity;
q->data[q->tail] = strdup(item);
q->size++;
return 1;
}
}
char *queue_dequeue(queue *q) {
if(q == NULL) return NULL;
else if(queue_empty(q) == 1) return '\0';
else {
char *item = q->data[q->head];
q->head = (q->head + 1) % q->capacity;
q->size--;
return item;
}
}
unsigned int queue_size(queue *q) {
if (q == NULL) return - 1;
else return q->size;
}
void free_queue(queue *q) {
for(int i = 0; i < q->capacity; i++) free(q->data[i]);
free(q->data);
free(q);
}
I'm using the usb for debbugging and when I send a simple command (via the arduino IDE) like $MOVE / I can receive it correctly but not send it back as serial, instead with the usb I can ( the printf under the uart_write_blocking).
When I try to send via uart I get random characters on the arduino serial prompt and the pico also seems to receive some of the ones it sent.
What are the random characters on the serial prompt? and what characters do you expect?
The third argument (length) of uart_write_blocking is hardcoded to 32, so this function will always try to send 32 bytes back to the raspberry pi -- that could cause some random characters to show up if the string the pico is trying to send is actually less than that. I'd try changing this code snippet to this and see if that stops the random characters.
printf("Trying to send something\n");
char *foo = queue_dequeue((queue*)tx_queue);
uart_write_blocking(UART_ID, (char*)foo, strlen(foo)); // only send as many bytes as are in the string

Windows API to Arduino Serial write works once but sends corrupted data when the same message is rewritten

I am using a third party WinAPI-based Serial library (SerialPort) in a C++ program to command a LED strip (iLED and pixel color), but it turns out it only seems to work for one command - if I send the same command a second time, the color of that pixel takes another random colour and for some reason the first LED turns on too with a random colour.
Here is a link to a video of what happens when the simplified code below is run, i.e. when pixel 3, 5 and 7 are commanded over and over to be red, green, and blue respectively.
https://drive.google.com/file/d/1RRAshnhPz96YGJtmETy3vuGi25QjxqJz/view?usp=drivesdk
I suspected the Serial.read() weren't synchronised so I added a start byte but it didn't seem to work either, that's what the code below does.
What is happening ?
SerialPort.h (source: https://blog.manash.me/serial-communication-with-an-arduino-using-c-on-windows-d08710186498)
#ifndef SERIALPORT_H
#define SERIALPORT_H
#define ARDUINO_WAIT_TIME 2000
#define MAX_DATA_LENGTH 255
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class SerialPort
{
private:
HANDLE handler;
bool connected;
COMSTAT status;
DWORD errors;
public:
SerialPort(char const *portName, unsigned long baudrate);
~SerialPort();
int readSerialPort(char *buffer, unsigned int buf_size);
bool writeSerialPort(char *buffer, unsigned int buf_size);
bool isConnected();
};
#endif // SERIALPORT_H
SerialPort.cpp (source: https://blog.manash.me/serial-communication-with-an-arduino-using-c-on-windows-d08710186498)
#include "serialport.h"
SerialPort::SerialPort(char const *portName, unsigned long baudrate)
{
this->connected = false;
this->handler = CreateFileA(static_cast<LPCSTR>(portName),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (this->handler == INVALID_HANDLE_VALUE){
if (GetLastError() == ERROR_FILE_NOT_FOUND){
printf("ERROR: Handle was not attached. Reason: %s not available\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else {
DCB dcbSerialParameters = {0};
if (!GetCommState(this->handler, &dcbSerialParameters)) {
printf("failed to get current serial parameters");
}
else {
dcbSerialParameters.BaudRate = baudrate;
dcbSerialParameters.ByteSize = 8;
dcbSerialParameters.StopBits = ONESTOPBIT;
dcbSerialParameters.Parity = NOPARITY;
dcbSerialParameters.fDtrControl = DTR_CONTROL_ENABLE;
if (!SetCommState(handler, &dcbSerialParameters))
{
printf("ALERT: could not set Serial port parameters\n");
}
else {
this->connected = true;
PurgeComm(this->handler, PURGE_RXCLEAR | PURGE_TXCLEAR);
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
SerialPort::~SerialPort()
{
if (this->connected){
this->connected = false;
CloseHandle(this->handler);
}
}
int SerialPort::readSerialPort(char *buffer, unsigned int buf_size)
{
DWORD bytesRead;
unsigned int toRead;
ClearCommError(this->handler, &this->errors, &this->status);
if (this->status.cbInQue > 0){
if (this->status.cbInQue > buf_size){
toRead = buf_size;
}
else toRead = this->status.cbInQue;
}
if (ReadFile(this->handler, buffer, toRead, &bytesRead, NULL)) return bytesRead;
return 0;
}
bool SerialPort::writeSerialPort(char *buffer, unsigned int buf_size)
{
DWORD bytesSend;
if (!WriteFile(this->handler, (void*) buffer, buf_size, &bytesSend, 0)){
ClearCommError(this->handler, &this->errors, &this->status);
return false;
}
else return true;
}
bool SerialPort::isConnected()
{
return this->connected;
}
main.cpp
#include <iostream>
#include "serialport.h"
using namespace std;
int main()
{
SerialPort serial("COM3", 115200);
while(1) {
unsigned char buffer[] = {255,3, 254, 0, 0};
serial.writeSerialPort((char*)buffer, 4);
unsigned char buffer2[] = {255,5, 0, 254, 0};
serial.writeSerialPort((char*)buffer2, 4);
unsigned char buffer3[] = {255,7, 0, 0, 254};
serial.writeSerialPort((char*)buffer3, 4);
}
return 0;
}
Arduino firmware
#include <FastLED.h>
#define BAUDRATE 115200
#define N_BYTES_MSG 4
#define N_LEDS 120
#define DATA_PIN 6
CRGB leds[N_LEDS] = {0};
void setup() {
FastLED.addLeds<WS2811, DATA_PIN, BRG>(leds, N_LEDS); //I don't know why the colours are BRG on this strip
FastLED.show();
Serial.begin(BAUDRATE);
}
void loop() {
//Check for a quadruplet of bytes (iLED R G B) led by start byte
if(Serial.available() >= N_BYTES_MSG+1 && Serial.read() == 255) {
//Read message
unsigned char buf[N_BYTES_MSG] = {0};
for(unsigned char i=0; i < N_BYTES_MSG; i++) {
buf[i] = Serial.read();
}
if(buf[0] < N_LEDS) { //Valid ID
leds[buf[0]] = CRGB(buf[1],buf[2],buf[3]); //Update LED state in internal representation
FastLED.show(); //Refresh LEDs based on internal representation
}
}
}
Note that the LED strip seems to work properly on its own, since I successfully tested moving at constant speed a single pixel.
The LED strip itself is the easiest debug route I have since I didn't manage to make readSerialPort() work yet and the COM port is hogged by the program so I can't get a handle on it (can we sniff that somehow?).
I test serial.writeSerialPort on Windows 10 desktop with Arduino Uno. It works for me.
The following is the code I used:
On windows:
#include <iostream>
#include "serialport.h"
using namespace std;
int main()
{
SerialPort serial("COM4", 115200);
while (1) {
unsigned char buffer[] = { 255,3, 254, 0, 0 };
serial.writeSerialPort((char*)buffer, 5);
unsigned char buffer2[] = { 255,5, 0, 254, 0 };
serial.writeSerialPort((char*)buffer2, 5);
unsigned char buffer3[] = { 255,7, 0, 0, 254 };
serial.writeSerialPort((char*)buffer3, 5);
}
return 0;
}
On Arduino:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
#define BAUDRATE 115200
#define N_BYTES_MSG 4
#define N_LEDS 120
#define DATA_PIN 6
void setup() {
Serial.begin(BAUDRATE);
mySerial.begin(BAUDRATE);
mySerial.println("Start reading.");
delay(5000);
}
void loop() {
//Check for a quadruplet of bytes (iLED R G B) led by start byte
if(Serial.available() >= N_BYTES_MSG+1 && Serial.read() == 255) {
//Read message
unsigned char buf[N_BYTES_MSG] = {0};
for(unsigned char i=0; i < N_BYTES_MSG; i++) {
buf[i] = Serial.read();
}
for(unsigned char i=0; i < N_BYTES_MSG; i++) {
mySerial.print(buf[i]);
mySerial.print(",");
}
mySerial.print("\r\n");
//Serial.write("Read complete!");
}
}
I print the received data on Arduino:
I notice that the printed data messed up when the Windows sends fast as you did in the while(1) without delay. So try adding a delay between two writes to see if it works.
Add also note the problem as #paddy pointed out.
I didn't manage to make readSerialPort() work yet
Set unsigned int toRead = buf_size; in SerialPort.cpp works for me. Use the following code to read:
unsigned char readBuffer[20] = {};
serial.readSerialPort((char*)readBuffer, 20);
printf((char*)readBuffer);
printf("\n");
Read from Arduino result:

Testing arduino gps

Me and and a friend of mine are building a robot which contains a gps for arduino. We built the following circuit, to test the gps:
We're trying the following code to test the gps:
#include <SoftwareSerial.h>
#include <TinyGPS.h>
long lat,lon; // create variable for latitude and longitude object
SoftwareSerial gpsSerial(2, 3); // create gps sensor connection
TinyGPS gps; // create gps object
void setup(){
Serial.begin(9600); // connect serial
gpsSerial.begin(4800); // connect gps sensor
}
void loop(){
Serial.print("test"); //I implemented this test
while(gpsSerial.available()){ // check for gps data
Serial.print("test2"); //I implemented this test
if(gps.encode(gpsSerial.read())){ // encode gps data
Serial.print("test3"); //I implemented this test
gps.get_position(&lat,&lon); // get latitude and longitude
// display position
Serial.print("Position: ");
Serial.print("lat: ");Serial.print(lat);Serial.print(" ");// print latitude
Serial.print("lon: ");Serial.println(lon); // print longitude
}
}
}
The thing is that the serial monitor does output test number 1, but doesn't output test number 2 and number 3. So we expected the circuit we built to fail. But we double checked the wires etc. Does anybody know what the problem could be?
Any inspiration/help is welcome,
Thanks,
Justin van Til
Try this code.
#include <SoftwareSerial.h>
#include <TinyGPS.h>
TinyGPS gps;
static void print_long(long val, long invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
SoftwareSerial ss(3,4);
void setup()
{
Serial.begin(9600);
ss.begin(9600);
}
void loop()
{
long lat, lon;
int alt;
unsigned short sentences = 0, failed = 0;
gps.get_position(&lat, &lon);
alt=gps.altitude();
Serial.print("CURRENT LATITUDE & LONGITUDE:");
Serial.print(lat);
Serial.print(",");
Serial.println(lon);
Serial.print("CURRENT ALTITUDE:");
Serial.println(alt);
smartdelay(1000);
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void print_long (long val, long invalid, int len, int prec)
{
if (val == invalid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(' ');
}
smartdelay(0);
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
Serial.print(sz);
smartdelay(0);
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
smartdelay(0);
}

Message Queue keeps sending/recieving garbage

In my assignment I have to fork processes to simulate a distributed operating system with process allocating using Heuristic Algorithm On Linux using IPC.
Now I fork n children and then make them simulate the algorithm, that's not the problem though the problem is in the message queue connections between all of them
There is 2 message queues UP and DOWN they are both not working atm.
Every time I try to send something over any of these queues they are received at the other side as garbage.
So, I use this struct and those methods for dealing with message queue
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
struct msgbuff
{
long mtype;
char mtext[70];
};
void Send(key_t msgqid,char* S,long pid)
{
int send_val;
struct msgbuff message;
message.mtype = pid; /* arbitrary value */
strcpy(message.mtext,S);
cout<<"Message is "<<message.mtext<<endl;
//strcpy(message.mtext, str);
cout<<getpid()<<" Entering Send process"<<endl;
send_val = msgsnd (msgqid, &message, sizeof(message), IPC_NOWAIT);
if(send_val == -1)
perror("Error in send");
}
char* Recieve(key_t msgqid,bool nowait)
{
int rec_val;
struct msgbuff message;
cout<<getpid()<<" Entering Receive process"<<endl;
/* receive all types of messages */
if(nowait)
rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), IPC_NOWAIT);
else rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), !IPC_NOWAIT);
if(rec_val == -1){
// perror("Error in receive");
return "none";
}
return message.mtext;
}
Then I use them at every child like so
DOWN = msgget(200, IPC_CREAT|0644);
UP = msgget(201,IPC_CREAT|0644);
And
while(1)
{
int countfail =0;
char* ask =Recieve(DOWN,true); //nowait
string asks(ask);
cout<<getpid()<<" ask= "<<asks<<endl; //This here prints either garbage (symbols and other random characters) or "none"
if(strcmp(ask,"none")!=0)
{
///////Logic for the algorithm
cout<<"*********"<<getpid()<<" In ASK "<<endl;
stringstream ss1;
ss1.str(ask);
int senderpid=0,processSize=0;
ss1>>processSize>>senderpid;
char* processRecMessage = new char[70];
///setting up what will be sent to other process
if(count+ processSize <= load)
{
count+=processSize;
strcpy(processRecMessage,"Taken");
}
else
{
strcpy(processRecMessage,"Not Taken");
}
//Another Garbage here
Send(UP,processRecMessage,senderpid);
}
else{
int nextProcess = (rand()%3) +1;
if(count + nextProcess <=load)
{
count +=nextProcess;
}
else{
for(int k = 0;k<3;k++)
{
int selectedChild = rand()%n;
cout<<getpid()<<" Selected Child no "<<selectedChild+1<<" PID="<<children[selectedChild]<<endl;
char* x = new char[70];
stringstream ss;
ss<<nextProcess;
ss<<" "<<getpid();
strcpy(x,ss.str().c_str());// x= "nextProcess pid"
cout<<x<<endl;
//// sending here also recieves garbage
Send (DOWN , x,children[selectedChild]);
//// receiving garbage
x= Recieve(UP,false);
cout<<getpid()<<" UP Value = "<<x<<endl;
if (strcmp(x,"Taken")==0){
cout<<"Process sent from "<<getpid()<<" to "<<children[selectedChild]<<endl;
break;
}
else
{
countfail++;
printf("TRAIL #%d failed\n",countfail);
}
}
if(countfail==3)
{
cout<<"Algorithm failed to allocate process.\n";
cout<<"Terminating Process "<<getpid()<<endl;
break;
}
}
}
}
So If anyone could help me with this I would be grateful
p.s.:
I delete all message queues after each fail run of the program so each time they start anew but still no use.
edit:
Adding the full code
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <math.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <string.h>
#include <map>
#include <sstream>
#include <ctime>
using namespace std;
struct msgbuff
{
long mtype;
char mtext[70];
};
void Send(key_t msgqid,char* S,long pid)
{
int send_val;
struct msgbuff message;
message.mtype = pid; /* arbitrary value */
strcpy(message.mtext,S);
cout<<"Message is "<<message.mtext<<endl;
//strcpy(message.mtext, str);
cout<<getpid()<<" Entering Send process"<<endl;
send_val = msgsnd (msgqid, &message, sizeof(message), IPC_NOWAIT);
if(send_val == -1)
perror("Errror in send");
}
char* Recieve(key_t msgqid,bool nowait)
{
int rec_val;
struct msgbuff message;
cout<<getpid()<<" Entering Receive process"<<endl;
/* receive all types of messages */
if(nowait)
rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), IPC_NOWAIT);
else rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), !IPC_NOWAIT);
if(rec_val == -1){
// perror("Error in receive");
return "none";
}
return message.mtext;
}
int main()
{
int n ;
pid_t pid;
key_t DOWN,UP;
DOWN = msgget(200, IPC_CREAT|0644);//Creates new identifier
UP = msgget(201,IPC_CREAT|0644);
int shmid;
shmid = shmget(50, 393216, IPC_CREAT|0644);
void *shmaddr;
shmaddr = shmat(shmid, (void *)0, 0);
printf("DOWN = %d\n", DOWN);
printf("UP = %d\n", UP);
cout<<"Please enter the number of machines "<<endl;
cin>>n;
int* children = new int[n];
string pids;
stringstream ss4;
ss4<<n;
string number = ss4.str();
pids+=number;
pids+=" ";
for (int i=0;i<n;i++)
{
pid = fork();
children[i]=pid;
stringstream ss3;
ss3<<pid;
string pidstr=ss3.str();
pids+=pidstr;
pids+=" ";
if (pid==0)
break;
}
if (pid==-1)
cout<<"Error in fork" <<endl;
else if (pid==0) // child
{
sleep(1);
DOWN = msgget(200, IPC_CREAT|0644);
UP = msgget(201,IPC_CREAT|0644);
//cout<<"Entering child process"<<endl;
shmid = shmget(50, 393216, IPC_CREAT|0644);
shmaddr = shmat(shmid, (void *)0, 0);
char* pidsrec = new char[100];
strcpy(pidsrec,(char*) shmaddr);
stringstream sss;
string spid(pidsrec);
sss.str(spid);
sss>>n;
children = new int[n];
for(int i =0;i<n;i++)
{
sss>>children[i];
//cout<<getpid()<<"Child #"<<i<<" = "<<children[i]<<endl;
}
srand(getpid());
int load = (rand()%10) +1; // load of operating on this system from 1-10
int count=0;
while(1)
{
int countfail =0;
char* ask =Recieve(DOWN,true); //nowait
string asks(ask);
cout<<getpid()<<" ask= "<<asks<<endl;
if(strcmp(ask,"none")!=0)
{
cout<<"*********"<<getpid()<<" In ASK "<<endl;
stringstream ss1;
ss1.str(ask);
int senderpid=0,processSize=0;
ss1>>processSize>>senderpid;
char* processRecMessage = new char[70];
if(count+ processSize <= load)
{
count+=processSize;
strcpy(processRecMessage,"Taken");
}
else
{
strcpy(processRecMessage,"Not Taken");
}
Send(UP,processRecMessage,senderpid);
}
else{
int nextProcess = (rand()%3) +1;
if(count + nextProcess <=load)
{
count +=nextProcess;
}
else{
for(int k = 0;k<3;k++)
{
int selectedChild = rand()%n;
cout<<getpid()<<" Selected Child no "<<selectedChild+1<<" PID="<<children[selectedChild]<<endl;
char* x = new char[70];
stringstream ss;
ss<<nextProcess;
ss<<" "<<getpid();
strcpy(x,ss.str().c_str());// x= "nextProcess pid"
cout<<x<<endl;
Send (DOWN , x,children[selectedChild]);
x= Recieve(UP,false);
cout<<getpid()<<" UP Value = "<<x<<endl;
if (strcmp(x,"Taken")==0){
cout<<"Process sent from "<<getpid()<<" to "<<children[selectedChild]<<endl;
break;
}
else
{
countfail++;
printf("TRAIL #%d failed\n",countfail);
}
}
if(countfail==3)
{
cout<<"Algorithm failed to allocate process.\n";
cout<<"Terminating Process "<<getpid()<<endl;
break;
}
}
}
}
}
else //parent
{
strcpy((char*) shmaddr,pids.c_str());
}
cout<<getpid()<<" GOODBYE"<<endl;
return 0;
}
I try it with any number of processes and there is always garbage received at the receive end of the message queue
In your Receive function, when you do
return message.mtext;
you are returning a pointer to data allocated locally on the stack. This area of the stack will not be valid after the function returns, and hence the dereferencing the pointer will cause undefined behavior. Also, if you use this pointer after calling another function, that area of the stack will most likely have been overwritten by the other function.
Since you're using C++, why not return std::string? It will solve this problem.

error: 'track_t' was not declared in this scope

I'm fiddling with an Arduino project where I've got these structs in my main file:
struct gpsCoord_t {
long latitude;
long longitude;
};
struct track_t {
char code[4];
gpsCoord_t bounds[4];
gpsCoord_t points[4];
};
Next to that I've got a function to dump variables of this type to the serial bus in that same file:
void dumpTrack(track_t track) {
Serial.print("\nTrack: ");
Serial.print(track.code);
Serial.print("\nTrack bounds: ");
Serial.print("\n- 1 lat: ");
Serial.print(track.bounds[0].latitude);
Serial.print("\n- 1 lon: ");
Serial.print(track.bounds[0].longitude);
}
The compiler produces 2 errors without line numbers from which I believe the first one is caused by the second one:
error: variable or field 'dumpTrack' declared void
error: 'track_t' was not declared in this scope
EDIT here's the complete file:
#include <Wire.h> //I2C library
#include <I2C_eeprom.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>
I2C_eeprom ee(0x50);
const int baseTrackAddress = 3;
const int trackSize = 68;
const int maxTracks = 480;
int powerOnLED = 2;
int gpsFixLED = 3;
int trackFoundLED = 4;
int errorLED = 6;
int gpsSensor = 7;
TinyGPS gps;
SoftwareSerial nss(gpsSensor, 255);
int calcTrackAddress(int trackId) {
return (trackId*trackSize) + baseTrackAddress;
}
struct gpsCoord_t {
long latitude;
long longitude;
};
struct track_t {
char code[4];
gpsCoord_t bounds[4];
gpsCoord_t points[4];
};
track_t tracks[maxTracks];
void setup()
{
Serial.begin(115200);
Serial.flush();
Serial.print("Demo I2C eeprom library ");
Serial.print(I2C_EEPROM_VERSION);
Serial.println("\n");
strcpy(tracks[0].code, "X11");
tracks[0].bounds[0].latitude = 0;
tracks[0].bounds[0].longitude = 0;
tracks[0].points[0].latitude = 0;
tracks[0].points[0].longitude = 0;
ee.writeBlock(3, (uint8_t*)&tracks[0], trackSize);
}
void loop()
{
Serial.println("\nTEST: 64 byte page boundary writeBlock");
dumpEEPROM(0, 255);
while(1);
}
void dumpTrack(track_t track) {
Serial.print("\nTrack: ");
Serial.print(track.code);
Serial.print("\nTrack bounds: ");
Serial.print("\n- 1 lat: ");
Serial.print(track.bounds[0].latitude);
Serial.print("\n- 1 lon: ");
Serial.print(track.bounds[0].longitude);
}
void readTrack(int trackId) {
track_t track;
ee.readBlock(60, (uint8_t*)&track, 10);
}
void readTracks() {
}
void dumpEEPROM(unsigned int addr, unsigned int length)
{
// block to 10
addr = addr / 10 * 10;
length = (length + 9)/10 * 10;
byte b = ee.readByte(addr);
for (int i = 0; i < length; i++)
{
if (addr % 10 == 0)
{
Serial.println();
Serial.print(addr);
Serial.print(":\t");
}
Serial.print(b);
b = ee.readByte(++addr);
Serial.print(" ");
}
Serial.println();
}
void ProcessCommand(char* command) {
//switch(*command==)
}
char* ReadSerialCommand() {
int i=0;
char commandbuffer[100];
if(Serial.available()){
delay(100);
while( Serial.available() && i< 99) {
commandbuffer[i++] = Serial.read();
}
commandbuffer[i++]='\0';
}
if(i>0)
return (char*)commandbuffer;
else
return 0L;
}
When I put the entire dumpTrack function in comment, the errors go away. I've checked a couple of times for a typo but failed to find any.
It seems you are compiling this code as C.
Instead of
struct track_t {
char code[4];
gpsCoord_t bounds[4];
gpsCoord_t points[4];
};
write
typedef struct {
char code[4];
gpsCoord_t bounds[4];
gpsCoord_t points[4];
} track_t;
I suspect somewhere in a header there is a variable called dumpTrack. Why don't you just rename the function to something else?
Also in general it is good to avoid using reserved words as function names; "loop" is not a good choice for a function name.
Edit: the latter is probably the reason for your problem.