Ho to use MODSERIAL inside my own library

11 Dec 2011

I'am new to mbed and C.

Since many hours i try to implement MODSERIAL into a library. Using MODSERIAL inside main.cpp is quite easy and works very well. But when I try to convert the code into a library it does not work. Even when I reduce the code to a minimum it compiles but it does not run (mled1 does not blink).

main.cpp

#include "SBUS.h"
#include "MODSERIAL.h"
#include "mbed.h"

DigitalOut mled1(LED1);
SBUS sbus2(p28, p27);   //when commented out, main() works

int main() {

    while (1) {
        wait(0.2);
        mled1=!mled1;
    }
}

SBUS.h

#ifndef MBED_SBUS_H
#define MBED_SBUS_H

#include "MODSERIAL.h"
#include "mbed.h"

class SBUS {
public:
    SBUS(PinName tx, PinName rx);
    MODSERIAL sbus_;
};

#endif

SBUS.cpp

#include "SBUS.h"
#include "MODSERIAL.h"
#include "mbed.h"

DigitalOut mled2(LED2);

SBUS::SBUS(PinName tx, PinName rx) : sbus_(tx, rx) {
    mled2=1;
}

Do I miss something? How to use the .attach functionality?

thanks

12 Dec 2011

Does it work if you comment out the mled2=1; line in the constructor of the SBUS class?

This line is a bit dangerous since you are calling the method of one global object (mled2) from the constructor of another global object (sbus2) and there is no guaranteed order for how such global constructors are called. You might be calling the assignment operator on mled2 before its constructor has even had a chance to run. If you really need mled2 to be part of the SBUS class then it should be a member of SBUS and not a global.

12 Dec 2011

Adam, your are right. Comment out this line helps. mled2 was just for debugging, seeing the constructor code executed.

I forgot that everything is an object. :-)

Many thanks

04 Aug 2012

Hi, I have used the serial ports separately, but now my application requieres 2 serial ports, but i fail. i have tested separatedly and works!, the first device is an IMU at 57600 baudrate, the other is a xbee working at 115200, i work with interrupts and the scanf. but i dont know if is not possible to use 2 interruptions? could someone tell me what could be happening? because its rare, the IMU is always connected to mbed, and scanf works good, then the xbee starts the transmission and the scanf of IMU sucks :( and the scanf of xbee works properly, if i cancell the attach of IMU the xbee also works good, but at same time fail.

#include "mbed.h"

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
DigitalOut dg(p21);
DigitalOut dh(p22);

Serial imu(p9,p10);// tx,rx
Serial xbee(p13,p14);

float Y=0,P=0,R=0;
int pd=0,rd=0,yd=0,act=0;
void rximu() {
    led3 = !led3;
    dg=1;
    imu.scanf("#YPR=%f,%f,%f\r\n",&Y,&P,&R);
    if(R>0){
      led1=1;
    }else{
      led1=0;
    }
    dg=0;
}

void rxbee() {
    led2 = !led2;
    dh=1;
    xbee.scanf("X:%d,%d,%d,%d\r",&pd,&rd,&yd,&act);
    if(act==1){
    led4=1;
    }else{
    led4=0;
    }
    dh=0;
}

int main() {    
    imu.baud(57600);
    xbee.baud(115200);  
    imu.attach(&rximu);
    xbee.attach(&rxbee);
    while(1) {
    }
}

Thanks

04 Aug 2012

@Sergio, the scanf is a blocking function that does not return until it detects a character that does not fit the format string. The first serial port that receives data will block the second. This may lead to dataloss on the second port. The attach function is in fact activated on every received character. I recommend that you use the callback only to receive and store a single character and that you do the decoding in your main loop. You may also want to look into MODSERIAL that does some buffering for you which might solve the problem.

05 Aug 2012

Wim Huiskamp wrote:

@Sergio, the scanf is a blocking function that does not return until it detects a character that does not fit the format string. The first serial port that receives data will block the second. This may lead to dataloss on the second port. The attach function is in fact activated on every received character. I recommend that you use the callback only to receive and store a single character and that you do the decoding in your main loop. You may also want to look into MODSERIAL that does some buffering for you which might solve the problem.

That was the solution, i read the MODSERIAL documentation and modified a program, the process is move the data to buffer, update a flag and decode in main. i post the program if anyone has a similar problem, this is not the end of my aplication but the data is ok. Thank you very much.

#include "mbed.h"
#include "MODSERIAL.h"

#define TAMANO_BUFFER 35

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

MODSERIAL imu(p9,p10);
MODSERIAL xbee(p13,p14);

char bufferEntrante[TAMANO_BUFFER];
char bufferEntrante2[TAMANO_BUFFER];
//char messageBufferOutgoing[TAMANO_BUFFER];
bool imuDato;
bool xbeeDato;
float Y=0,P=0,R=0;
int pd,rd,yd,act;

void imuRx(MODSERIAL_IRQ_INFO *q) {
    led1=!led1;
    MODSERIAL *sys = q->serial;
    sys->move(bufferEntrante, TAMANO_BUFFER);
    imuDato = true;
}

void xbeeRx(MODSERIAL_IRQ_INFO *q) {
    led2=!led2;
    MODSERIAL *sys2 = q->serial;
    sys2->move(bufferEntrante2, TAMANO_BUFFER);
    xbeeDato = true;
}

void procesarImu(void) {
    sscanf(bufferEntrante,"#YPR=%f,%f,%f\r",&Y,&P,&R);
    if (P>0) {
        led3=1;
    } else {
        led3=0;
    }
    imuDato = false;
}

void procesarXbee(void) {
    sscanf(bufferEntrante2,"X:%d,%d,%d,%d",&pd,&rd,&yd,&act);
    if (act==1) {
        led4=1;
    } else {
        led4=0;
    }
    xbeeDato = false;
}


int main() {

    imuDato = false;
    xbeeDato = false;
    imu.baud(57600);
    imu.attach(&imuRx, MODSERIAL::RxAutoDetect);
    imu.autoDetectChar('\n');
    
    xbee.baud(115200);
    xbee.attach(&xbeeRx, MODSERIAL::RxAutoDetect);
    xbee.autoDetectChar('\r');

    while (1) {
        if (imuDato){
           procesarImu();
        }   
        if (xbeeDato){
         procesarXbee();
        }
    }
}