QTime or QTimer wait for timeout - qt

I'm writting a Qt application, and I have a four hour loop (in a seperate thread). In that four hour loop, I have to:
do stuff with the serial port;
wait a fixed period of time;
do some more stuff with the serial port;
wait an arbitrary amount of time.
when 500ms have past, do more stuff;
Go to 1. and repeat for four hours.
Currently, my method of doing this is really bad, and crashes some computers. I have a whole bunch of code, but the following snippet basically shows the problem. The CPU goes to ~100% and eventually can crash the computer.
void CRelayduinoUserControl::wait(int timeMS)
{
int curTime = loopTimer->elapsed();
while(loopTimer->elapsed() < curTime + timeMS);
}
I need to somehow wait for a particular amount of time to pass before continuing on with the program. Is there some function which will just wait for some arbitrary period of time while keeping all the timers going?

If you want to sleep in QT, use QTimer. Just connect the timeout signal from the timer to the slot that contains the code you want to do every x amount of time.

IMO you should use the signal/slot mechanism in spite of waiting inside a while. Code could be something like that:
#define STATE_1 0x01
#define STATE_2 0x02
#define STATE_3 0x03
.....
QTimer * timer = new QTimer();
connect(timer,SIGNAL(timeout()),SLOT(timerSlot()));
int state = STATE_1 ;
timer->timerSlot()
....
void timerSlot() {
switch(state) {
case STATE_1:
// do stuff with the serial port
state = STATE_2;
timer->start(time_to_wait_in_ms);
break;
case STATE_2:
// do more stuff with the serial port
state = STATE_3;
timer->start(500);
break;
case STATE_3:
// do more stuff
state = STATE_1;
timer->start(1000*60*60*4);
break;
}

Related

Why does the IR reciver gives diffrent value everytime I try to break a for loop - when new value is recived, Arduino ide?

I am new to Arduino programming and was trying to make an IR-controlled WS2812 led strip light, everything works fine apart from when I try to stop the for-loop when my IR receiver gets a new decoded value. It does get the job done but the received values are different every time. when I tested the same controller with a simple IR receiver program everything worked fine.
switch(value){
case 16720095:
delay (200);
irrecv.resume();
for (int i = 0; i <= 182; i++) {
leds[i] = CRGB (0,0,0);
FastLED.show();
if (irrecv.decode(&results))
{
value = results.value;
Serial.println(value);
break;
}
delay(40);
}
}
}
and the serial outputs:
first time:
16720095
-1572362453
second time:
16720095
-1406992986
third time:
16720095
811035822
It looks like you need to call "irrecv.resume()" within the if (irrecv.decode(&results)) block in order to tell the driver to keep looking for signals. The second values you are getting are garbage because you are asking it to provide data it hasn't received/ prepared.

Arduino Function Execution Time

I have an Arduino and an APC220 wireless transceiver. I'm writing a library that reads in data from the APC using the SoftwareSerial class. I originally started with the (incorrect) code below that was causing a seg fault because the i variable is incremented even when there is no data available to read. In cases where it happened to work (by chance when the data was immediately available), this function took approximately 6 milliseconds to execute. When I put the i++; statement in its proper place (above the closing brace immediately above it), the function takes over 270 ms to run. Speed is crucial for this function, so I'm wondering what it is about that statement's placement that causes such a dramatic increase in time.
For the code below, buff is declared as char buff[10]; and sSerial is an instance of SoftwareSerial
unsigned long updateLocation(Marker* marker) {
this->sSerial->print('~');
//initiate request from vision system
this->sSerial->flush();
this->sSerial->print('#');
this->sSerial->print(marker->num);
this->sSerial->print('*');
this->sSerial->flush();
unsigned long start = millis();
int state = 0, i = 0;
while((millis() - start) < 600) {
if(this->sSerial->available()) {
buff[i] = this->sSerial->read();
if(buff[i] == ',') {
buff[i] = 0;
switch(state) {
case 0:
i = -1;
state++;
break;
case 1:
marker->x = atof(buff);
i = -1;
state++;
break;
case 2:
marker->y = atof(buff);
i = -1;
state++;
break;
case 3:
marker->theta = atof(buff);
i = -1;
return (millis() - start);
break;
default:
return 0;
break;
}
}
// Correct location for i++; takes 270 ms to execute
}
// Incorrect location for i++; Takes 6 ms to execute
i++;
}
this->sSerial->print('~');
this->sSerial->flush();
return 0;
}
Assuming that there's data ready and waiting from sSerial, there's no effective difference in the placement of i++.
You said yourself, in most cases the data isn't ready. With the incorrect placement of i++, i quickly grows to greater than the size of buff which causes the segfault.
With the correct placement, your code blocks for up to 600ms waiting for enough data to come in to reach case 3 and return. On average, you're seeing that it takes 270ms for that to happen.
You can test this theory yourself by timing the same function operating directly on a string rather than reading in from serial.
You may want to a) increase your baud rate b) check to see if there's a more efficient software serial implementation you can use c) switch to hardware serial. If you are only using hardware serial currently for debugging output, you can switch that around. Use an FTDI adapter ($6-10 on eBay) to pipe software serial to USB and reserve the hardware serial for your time sensitive function.
You might also be able to reconfigure your code so it doesn't block the whole time waiting. You can read in what's available, store it in a global and go back to your main loop to do something else until there's data available again.
edit: I see now that the APC220 is 9600 baud max. That's pretty slow, so the bottle neck may not be software serial (but you should test it). If the bottle neck is simply the baud rate, you will need to look at optimizing your code not to block waiting for input if there are other things your system can work on while it's waiting.

xbee: receive messages from an interrupt

I intend to read the data received by the xbee in an interrupt handler.
But as the handler can not use delays, I can not use readPacket (100).
I have the following code:
#include <XBee.h>
#include <avr/power.h>
#include <avr/sleep.h>
XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
ZBRxResponse rx = ZBRxResponse();
int size;
uint8_t buffer[256];
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
xbee.begin(Serial1);
attachInterrupt(0, wake_up_now, LOW );
}
void wake_up_now() {
xbee.readPacket();
if(xbee.getResponse().isAvailable()){
if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
xbee.getResponse().getZBRxResponse(rx);
size = rx.getDataLength();
for (int i = 0; i < size; i++)
buffer[i] = rx.getData(i);
}
}
}
void sleepNow() {
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_twi_disable();
sleep_mode();
sleep_disable();
power_all_enable();
}
void loop() {
Serial.print("Awake");
Serial.println(size);
for (int i = 0; i < size; i++)
Serial.println(buffer[i]);
Serial.println("Entering Sleep mode");
delay(100);
sleepNow();
}
If you receive data the first time I can not read this data.
But later, when more data is received the data that was sent in the first message is read.
I really need to read the data in the handler, how can I solve this?
When I designed this ANSI C XBee Host library, I thought I could include frame processing as part of the serial interrupt handler on the Freescale HCS08 platform. I found that it just didn't work well, especially at a baud rate of 115,200.
The final design I went with was to keep a buffer of bytes from the serial port, and parse/dispatch frames in a "tick" function called in my main event loop. In one application, I was calling the "tick" function at least once every 50ms (IIRC).
As for forcing the XBee module to buffer serial data while you're sleeping, I think you'll have a hard time with that. You'd need to deassert RTS, but then wait to see if the XBee was still sending you a byte. My recollection is that I would still get multiple bytes (3 or 4?) after deasserting RTS. You'll also have to handle the condition of getting a partial packet while you're awake, and needing to decide whether you'll receive the whole frame then, or the next time you wake up.
You'd probably be better off using the XBee module's SPI interface, since the host controls when bytes are sent, and it might even be possible to have the XBee trigger a hardware interrupt on the host when it has bytes to send. You can also use high speeds (460kbps and up, I believe) to get the bytes quickly.

Arduino DUE, Serial interrupt procedure to wakeup from sleep mode

i'd like to put the SAM3X chip on sleepmode until a character arrives on the serial port. i was thinking of using an ausiliary flag in the Serial interrupt procedure in order to trigger the wake up procedure? what do you think abou? any advice or any other way i should follow or try?
I recommend reviewing .\arduino-1.5.2\hardware\arduino\sam\cores\arduino\UARTClass.cpp as its UARTClass::begin will detail how the Arduino Framework initializes the SAM's Serial IRQ with:
// Configure interrupts
_pUart->UART_IDR = 0xFFFFFFFF;
_pUart->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;
// Enable UART interrupt in NVIC
NVIC_EnableIRQ(_dwIrq);
// Enable receiver and transmitter
_pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN ;
Where you will need to ensure the baud rate generator is not stopped while in sleepmode.
Along with reading the SAM3X data sheet starting with 5.5.3. which leaves the peripheral clocks enabled.
looks like you may be able to insert the wake up into the UARTClass::IrqHandler
void UARTClass::IrqHandler( void )
{
uint32_t status = _pUart->UART_SR;
// Did we receive data ?
if ((status & UART_SR_RXRDY) == UART_SR_RXRDY)
{
// wake up!!!! Not sure if you even need to wakeup, it should from the sleepmode
_rx_buffer->store_char(_pUart->UART_RHR);
}
With regards to sleeping:
\arduino-1.5.2\hardware\arduino\sam\system\libsam\source\pmc.c
Line 972: void pmc_enable_sleepmode(uint8_t uc_type)
Line 988: void pmc_enable_waitmode(void)
Line 1009: void pmc_enable_backupmode(void)
So I would suspect the following:
pmc_enable_sleepmode(WFI);
would put the unit a sleep and the IrqHandler of the UART_SR_RXRDY would wake itself up, without any code change.
One other alternative would be to use the serial pin's IO as to trigger an interrupt.
attachInterrupt(0, EnableSerialRX, CHANGE);
It would though, loose at least the first byte. the trade off is that you can use the lower power modem of pmc_enable_backupmode() rather than sleep

Make my arduino accomplish task at specific time

I'm a newbie to arduino. What I need is make him do something at specific time, and go to sleep, so that it doesn't work excessively.
Specific task is: I want him to start a mechanism for feeding my gold fish, so in vacation time arduino should work for 10 days or more (this is reason for sleep mode).
When researching this problem, I came up with time interrupts, but I don't think this is best solution, because I want him do something at specific time, not to to interrupt his task.
Thank you for any kind of help :)
I've read that the standard Arduino board doesn't save that much power, as the power regulator and USB port (if present) draws significant power. But given that you use an external clock to trigger the device to wakeup, there's a simple arduino library, Enerlib, that you can use.
Engblaze has a nice article on how to do it yourself, but if you're new to the arduino, you might not want to jump into AVR libraries.
you can try something easy like every 30 seconds starts an event of 20 seconds of duration :
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
void setup () {
Serial.begin(57600);
#ifdef AVR
Wire.begin();
#else
Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
rtc.begin();
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
}
}
boolean pumpOn = false;
void loop () {
DateTime now = rtc.now();
if(now.second()%30==0){ pumpOn=true;}
if(now.second()%50==0){ pumpOn=false;}
if(pumpOn)
Serial.println("on");
}
}
Use the millis() method. It will reset after 50 days but I don't think you will be traveling for so long...
unsigned long hours4nextFeeding = 8;
unsigned long lastTime = millis();
void loop() {
if(millis() > (lastTime + (hours4nextFeeding*3600*1000))) {
feedTheFish();
lastTime = millis();
}
delay(60000);
}
Also you can use a light sensor (supercheaper) and feed the fish once a day when the sun rises
The code I just wrote is untested but you should get the idea.
I like #Josh's solution of using the clock to reset the device, but here's another idea if your fish will die if they aren't fed on the millisecond.

Resources