GPS data blocked by other tasks in the while loop - gps
I am trying to parse GPS data while reading pressure sensor, IMU sensor and writing some data to SD card. Since reading pressure sensor, IMU sensor and writing SD card takes some time and GPS don't wait my command to send its data, I lost some GPS data so my parser can not find meaningful message. I use uart_receive interrupt to take GPS data and circular buffer to save its data. After I parse it. Since I don't know how much bytes come from GPS, I read one by one. I tried FreeRTOS but it did not work. How can I prevent other tasks to block GPS data. I am using STM32f401cc.
Here is my FreeRTOS task;
void StartDefaultTask(void* argument)
{
IMU_setParameters(&imu, &hi2c1, imu_ADD_LOW, GPIOB, GPIOB,
GPIO_PIN_1, GPIO_PIN_2);
IMU_init(&imu, &htim3);
while ((calState.accel != 3 || calState.system != 3 || calState.gyro != 3 || calState.mag != 3) && calibFlg)
{
IMU_getCalibrationState(&imu, &calState);
}
preSensor_init_default_params(&preSensor.params);
preSensor.addr = preSensor_I2C_ADDRESS_1;
preSensor.i2c = &hi2c1;
preSensor_init(&preSensor, &preSensor.params);
initSD_CARD(&USERFatFS, USERPath);
samplePacket(&telemetry);
controlRecoveryFile(&recoveryFile, "recoveryFile.txt", &telemetry);
for (;;)
{
IMU_getDatas(&imu, &calState, &linearAccel, &IMU, &imuFlg, &offsetFlg, &calibCount);
preSensor_force_measurement(&preSensor);
preSensor_read_float(&preSensor, &temperature, &pressure, &humidty);
preSensor_get_height(pressure, &height);
telemetry.Altitude_PL = height;
telemetry.Pressure_PL = pressure;
telemetry.Temperature = temperature;
telemetry.YRP[0] = IMU.yaw;
telemetry.YRP[1] = IMU.roll;
telemetry.YRP[2] = IMU.pitch;
if (calibCount % 10 == 0)
{
writoToTelemetryDatas(&logFile, "tulparLog.txt", &telemetry, 0);
if (!writeToRecoveryDatas(&recoveryFile, "recoveryFile.txt", &telemetry))
connectionFlg = 1;
}
osDelay(1);
}
}
void StartTask02(void* argument)
{
arrangeCircularBuffer(&gpsCircular, buffer, BUFFER_LENGTH);
initGPS(&huart1, &rDATA, &gps);
for (;;)
{
getGPSdata(&huart1, &gpsCircular, &gps, &rDATA);
osDelay(1);
}
}
Here is my solution to problem.
First of all I do not use FreeRtos at all. I do all the thing in main loop. Problem is "Race Condition". In my GPS data parser, there are 4 states. MSG_ID, Finish, Check, Parse. These four states do not take four loops to find meaningfull message. It depends on message length. It can be at most 103 loop. Besides, In main loop my imu sensor, pressure sensor and SD card module takes approximately 80 ms. As you know, GPS works independent from our code. It does not wait our command to send data. Every 1 second it sends its datas. Now, imagine that your GPS sends datas every 1 seconds and your CircularBuffer has 200 bytes. Your parser begin to parse message. But your parser needs at least 30+ loops to find message. Now, 30*80 = 2400 ms (2.4 s). Untill you find meaningfull data GPS sent 2 more datas and overflow happened. To fix this situation, I write for loop for my GPS parser in the main loop and I send command to GPS for just taking GPGGA and GPRMC datas (for GPS command you can look at here. I use uart_receive_ınterrupt to store data to my circularbuffer. After taking 2 '\n', I stop taking data and wait my parser to parse these datas. At the end I start uart operation taking meaningfull datas. Important thing here is calling parser in a for loop. (it can be 8-16-24 loops depends on your other tasks delay)
Related
Unable to exit while loop in UVM monitor
This might be a silly mistake from my side that I have overlooked but I'm fairly new to UVM and I tried tinkering with my code for a while before this. I'm trying to send in a stream of 8 bit data within a packet using Data valid stall protocol from my UVM driver to the DUT. I'm facing an issue with my input monitor not being able to pick up these transactions that are driven. I have a while loop with a condition that the valid bit must be high and the stall bit should be low. As long as this condition holds good, the monitor needs to pick up the data byte and push into the queue. I know for a fact that the data is being picked up and pushed to a queue as I used $display statements along the way. The problem is arising once all the data bytes are received and the valid bit goes low. Ideally, this should cause the exit from the while loop but isn't doing so. Any help here would be appreciated. I have attached a snippet of the code below. Thanks in advance. virtual task main_phase (uvm_phase phase); $display("Run phase of input monitor"); collect_transfer(); endtask: main_phase virtual task collect_transfer(); fork forever begin wait_for_valid_transaction_cycle(); create_and_populate_pkt(); broadcast_pkt(); #(iP0_vif.cb_iP0_MON); end join_none endtask: collect_transfer virtual task wait_for_valid_transaction_cycle(); wait(iP0_vif.cb_iP0_MON.ip_valid && ~iP0_vif.cb_iP0_MON.ip_stall); endtask: wait_for_valid_transaction_cycle virtual task create_and_populate_pkt(); pkt = Router_seq_item :: type_id :: create("pkt"); pkt.valid = iP0_vif.cb_iP0_MON.ip_valid; pkt.sop = iP0_vif.cb_iP0_MON.ip_sop; $display("before data collection"); while(iP0_vif.cb_iP0_MON.ip_valid === `HIGH && iP0_vif.cb_iP0_MON.ip_stall === `LOW) begin $display("After checking for stall"); pkt.data = iP0_vif.cb_iP0_MON.ip_data; $display(pkt.data); pkt.data_q.push_front(pkt.data); pkt.eop = iP0_vif.cb_iP0_MON.ip_eop; $display("print check in input monitor # time = %0t", $time); #(iP0_vif.cb_iP0_MON); end $display("before printing input packet from monitor"); Check_for_port_route_and_populate_packet_field(pkt); print_packet(pkt); endtask: create_and_populate_pkt The $display statement "before printing input packet from monitor" is not being displayed. HIGH is defined as a binary 1 and LOW is defined as a binary 0. The output of the code in terms of display statements is as below. before data collection before checking for stall After checking for stall 2 print check in input monitor # time = 105 before checking for stall After checking for stall 1 print check in input monitor # time = 115 before checking for stall After checking for stall 3 print check in input monitor # time = 125
It's possible that the main phase objection is being dropped elsewhere in your environment. UVM will automatically kill any threads that were spawned during a phase when it ends. To fix this, do not object to the main phase in your monitor. Objecting to that phase is the responsibility of the threads creating the stimulus. Instead, you should be launching this monitor during the run_phase, which will ensure that your loop is not killed until the end of simulation. Also, during the shutdown phase, you will want your monitor to object whenever it is currently seeing a packet. This will ensure that simulation doesn't end as soon as stimulus has been sent in, giving your other monitors time to collect responses from the DUT.
Why are data packets missing in Zigbee arduino setup?
I made a setup which consists of 3 Zigbee's, 2 routers(Zigbee S2C's) and 1 coordinator(Zigbee S2). The routers are each connected to arduino nano which collects data from 2 FSR's and an IMU(frame type: zigbee transmit request and packet size 46 bytes) and sends it to the Coordinator attached to an arduino UNO. All the Xbees are in API mode 2 and working at a baud rate of 115200. I am using a library called "Simple Zigbee Library" to send all the collected data to the Coordinator. The collection and sending of data works fine except that there are packets lost in the way. The nano's sample data at a frequency of around 25Hz independently. The coordinator tries to read the data send from the zigbees(using the library of course) in every loop, but unfortunately, it seems to receive only around 40-45 samples.(Should have been 25*2=50 samples total from the 2 xbees). Can anybody suggest why this is happening. I need as less data loss as possible for my setup to achieve its motive. Any kind of help is appreciated. P.S: It may be important to mention that the coordinator is reading the data only from one xbee in each loop. As can be seen under the "Source" heading of this image of data received by the coordinator, "19" and "106" are the addresses of the routers and there are data packets dropped intermittently Thank you. void setup() { // Start the serial ports ... Serial.begin( 115200 ); while( !Serial ){;} // Wait for serial port (for Leonardo only). xbeeSerial.begin( 115200 ); // ... and set the serial port for the XBee radio. xbee.setSerial( xbeeSerial ); // Set a non-zero frame id to receive Status packets. xbee.setAcknowledgement(true); } void loop() { // While data is waiting in the XBee serial port ... while( xbee.available() ) { // ... read the data. xbee.read(); // If a complete message is available, display the contents if( xbee.isComplete() ){ Serial.print("\nIncoming Message: "); printPacket( xbee.getIncomingPacketObject() ); } } delay(10); // Small delay for stability // That's it! The coordinator is ready to go. } // Function for printing the complete contents of a packet // void printPacket(SimpleZigBeePacket & p) { //Serial.print( START, HEX ); //Serial.print(' '); //Serial.print( p.getLengthMSB(), HEX ); //Serial.print(' '); //Serial.print( p.getLengthLSB(), HEX ); //Serial.print(' '); // Frame Type and Frame ID are stored in Frame Data uint8_t checksum = 0; for( int i=10; i<p.getFrameLength(); i++){ Serial.print( p.getFrameData(i), HEX ); Serial.print(' '); checksum += p.getFrameData(i); } // Calculate checksum based on summation of frame bytes checksum = 0xff - checksum; Serial.print(checksum, HEX ); Serial.println(); }
Although you claim to be using 115,200bps, posted code shows you opening the serial ports at 9600 baud, definitely not fast enough for 2500 bytes/second (50 packets/second * 45 bytes/packet * 110% for overhead) received from XBee and dumped by printPacket()). Remember that 802.15.4 is always 250kbps over the air, and the XBee module's serial port configuration is just for local communications with the host. Make sure your routers are sending unicast (and not broadcast) packets to keep the radio traffic down. You should verify that sending is working before troubleshooting code on the coordinator. Update the code on your routers to see if you get a successful Transmit Status packet for every packet sent. Aiming for 50Hz seems like a bit much -- you're trying to send 45 bytes (is that the full size of the API frame?) every 20ms. Are you using a hardware serial port on the Arduino for both the XBee module and Serial.print()? How much time does each call to printPacket() take? If you reduce the code in printPacket() to a bare minimum (last byte of sender's address and the 1-byte frame ID), do you see all packets come through (an indication that you're spending too much time dumping the packets).
I'm concerned with the code you're using in loop. I don't know the deep internals of how the Arduino works, but does that 10ms delay block other code from processing data? What if you simplify it: void loop() { xbee.read(); // Process any complete frames. while (xbee.isComplete()){ Serial.print("\nIncoming Message: "); printPacket( xbee.getIncomingPacketObject() ); } } But before going too far, you should isolate the problem would by connecting the coordinator to a terminal emulator on a PC to monitor the frame rate. If all frames arrive then there's an issue on the coordinator. If they don't, work on your router code first.
GP-635T GPS module dropping data
I have a GP-635T GPS module attached to my Arduino UNO (GPS TX->UNO RX[Pin 0]) using Serial. Then I just read the incoming data byte for byte adding them to a string as they are read and when I reach a newline character(13) I just print the complete String of data and reset the data String for the next run. Code: void setup() { Serial.begin(9600); Serial.println("Initialized Serial port.."); } String data = ""; void loop() { while(Serial.available()) { char gpsByte = Serial.read();// Read a byte from the GPS data += gpsByte; if(gpsByte == 13){ Serial.print(data); data = ""; } } delay(100); } This code works as it is. But the problem here is the data I get from it. The module prints out multiple datalines at 1Hz using the NMEA-0183 standard. I do not have any idea how it decides what to print when because the data is not consistent for more than 5 "prints" of the (almost)complete dataset. Ex: $GPGGA,213948.00,,,,,0,00,99.99,,,,,,*63 $GPGSA,A30 <--- A30? $GPGSV,1,1,01,29,,,30*70 $GPGLL,,,,,213948.00,V,N*4F $GPRMC,213949.00,V,,,,,,,290314,,,N*74 $GPVTG,,,,,,,,,N*30 $GPGGA,213949.00,,,,,0,00,99.99,,,,,,*62 $GPGSA,A,1,,,,PGSV,1,1,01,29,,,30*70 <--- PGSV? $GPGLL,,,,,213949.00,V,N*4E $GPRMC,213950.00,V,,,,,,,290314,,,N*7C $GPVTG,,,,,,,,,N*30 $GPGGA,213950.00,,,,,0,00,99.99,,,,,,*6A ... $GPGGA,214045SA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30 $GPGSV,1,1,01,29,,,30*70$GPRMC,214046.00,V,,,,,,,290314,,,N*75 <--- Missing linebreak? $GPVTG,,,,,,,,,N*30 $G00,99.99,,,,,,*63 <--- $G00?? $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30 $GPGSV,1,1,02,20,,,27,29,,,30*74 $GPGLL,$GPRMC,214047.00,V,,,,,,,290314,,,N*74 <--- Missing data? $GPVTG,,,,,,,,,N*30 $GPGGA,214047.00,,,,,0,00,99.99,,,,,,*62 $,99.99*30 <--- Alot of missing data I think you get the point, I have nothing but the GPS connected to the Arduino. I have tried with sending the data wirelessly with some wireless modules with no change. I have tried with using AltSoftSerial and SoftwareSerial but I got messier data with the latter. I have tried different baud rates with no luck. Does anyone have any idea as to why this is happening? The module is brand new and I have no idea why it would behave like this. NOTE: I do not have a very good GPS signal to my module from within my house, I did try going outside with it and see if I could get a signal which I did from about 3 satellites, but that didn't change the output.
Well this was a very strange problem, The problem did go away when I shortened the delay from 100ms to 10ms. It might have to do something with the buffer and maybe it just gets overflowed before I start reading bytes from it. However if someone else have got this same problem, shorten the loop delay and you should be fine!
Error returned by Nuance DragonMobile text-to-speech when maximum number of transactions is reached
I'm about to release my App on IOS that uses Nuance Dragon Mobile SDK. I'm signed up for the "Silver" plan, which allows me 20 transactions per day. My question is, does anyone know what error is returned by Nuance, when the limit is exceeded? I'm concerned, because I am filtering out: error.code == 5 // Because this fires whenever I interrupt running speech error.code == 1 // Because after interrupting speech, the first time I restart, it cuts off // before finished, so I automatically start again, so as not to trouble the user to do so I figure if Nuance returns an error different from these, I'll allow it to pass through, and be able to alert the user that they've reached their daily limit. I think the following gives the possible errors: extern NSString * const SKSpeechErrorDomain; enum { SKServerConnectionError = 1, SKServerRetryError = 2, SKRecognizerError = 3, SKVocalizerError = 4, SKCancelledError = 5, }; It seems likely to me that it's the SKServerConnectionError that would be fired. In that case, I need to come up with a different strategy. If I could figure out what's going on with the restart issue I wouldn't have to filter out that error. Plus, when I automatically restart these false starts, I'm probably racking up my transaction count, which is unfortunate. Anybody have experience with this aspect of the Nuance SDK for IOS?
Why am I losing data when using a vxWorks pipe?
I am using pipes to transfer information between two vxWorks tasks. Here is a code sample: Init() { fd = open("/pipe/mydev", O_RDWR, 0777); ... } taskRx() { ... len = read(fd, rxbuf, MAX_RX_LEN); ... } taskTx() { ... len = write(fd, txbuf, txLen); ... } If we send a message that is longer than MAX_RX_LEN, (ie txLen > MAX_RX_LEN) we do 2 reads to get the remainder of the message. What we noticed is that the 2nd read didn't receive any data! Why is that?
VxWorks' pipe mechanism is not stream based (unlike unix named pipes). It is a layer on top of the vxWorks message Queue facility. As such, it has the same limitations as a message queue: when reading from the pipe, you are really reading the entire message. If your receive buffer does not have enough space to store the received data, the overflow is simply discarded. When doing a receive on a message Queue or a pipe, always make sure the buffer is set to the maximum size of a queue element.