How to use Serial as an interrupt for other functions - arduino

I'm making an LED control program (using FastLED, of course) and using Serial (with the Serial monitor) to control it. I just connected it via USB and for the most part it works just fine. However, I noticed with the long, flashing routines that I couldn't stop them and make the LEDs do something else. The flash routine in my code is very simple:
void flash(CRGB color, int count, int del){
for(int i = 0; i < count; i++){
if(pause){
break;
}
fillLeds(color.r, color.g, color.b);
milliDelay(del);
fillLeds(0,0,0);
milliDelay(del);
}
}
With fillLeds(r,g,b) being a for loop, looping through and setting all LEDs to a certain color, and milliDelay is just delay() using millis and not the delay() function.
I need to be able to pause not just this, but other functions as well (probably using break;) and then execute other code. It seems easy, right? Well, I've noticed that when I send a byte over Serial, it goes into this "queue," if you will, and then is sequentially read.
I can’t have this happen. I need the next byte entering Serial to activate some kind of event that pauses the other flash() function running, and then be used. I have implemented this like:
void loop()
{
if (Serial.available() > 0)
{
int x = Serial.read();
Serial.print(x);
handleRequest(x);
}
FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
}
Where handleRequest(x); is just a long switch statement with calls to the flash method, with different colors being used, etc.
How can I make the Arduino pause other loops whenever a new byte is received, instead of adding it to this "queue" to be acted upon later? If this is not possible thanks for reading anyway. I've tried using serialEvent() which doesn't appear to work.

I think you need two loops. You have one, which is your main loop, and you can add another (like a multi threading) with the TimerOne library. Like this:
Timer1.initialize(your desired delay in this loop);
Timer1.attachInterrupt(your desired function in this loop);
So maybe you can add an if statement with a variable in your second loop to prevent some function and update the variable in your first loop or something like that.

Presuming you want interrupt-like functionality when a new byte arrives:
Unfortunately, serialEvent() is not a true interrupt. It only runs at the end of loop(), if there is serial data available.
However, serialEvent() is just a function, and there isn't any reason why you can't call it in your code as often as you like. This is effectively polling for new serial data as often as possible. So, while your loops are running, call serialEvent() during your delays and handle the serial data there.
You may need to restructure your code to avoid recursion though. If flash calls serialEvent(), which calls flash, which calls serialEvent, etc... then you may end up overflowing the stack.

Related

Prevent unwanted Toggling in a Timer

I have a problem with arduino due timers. First let me explain what i know of them.I don't know if there is a way to solve this issue for general timers. Due timers features:
1) They always start from zero,
2) They work as UP-COUNTING or UP-DOWN counting timers,
3) Each timer has two compare registers.
My project involves cases to work in sampled times(period), i.e. timer runs for a sampled time and based on values in compare registers the outputs TIOA and TIOB toggles.I am working in up-down mode. Now the problem is when I have zero in a compare register I expect a zero output (on TIOA and TIOB) for whole period. But the timer is toggling output for zero comparison also. i.e. instead of getting a zero always i am getting a square wave with (2*period) as its time period. Is this common problem for other timers also?
Can you guys suggest me a workaround for this problem?
Thanks in advance.
#include <AdvaDueTC.h>
int default_clock = 1;
int RCcntS = 2187*2;
int period0 = 65536;
int a = 2180;
int b = 0;
void subrtn()
{
changeTC_TC3_Period(RCcntS); // loading sampler TC3 with RCcntS
changeTC_TC0_Period(RCcntS/2,a,b); // loading timer TC0 with RCcntT
}
void setup() {
setupTC3_Interrupt(period0,default_clock ,subrtn);//setup sampler interrupt
setupTC_TC0_Timing(period0, default_clock);
}
void loop() {
// put your main code here, to run repeatedly:
}
functions used are :
Here TC3 is in UP mode and TC0 is in UPDOWN mode of operation. TIOA0 and TIOB0 are used for obtaining toggling output.(i.e. in REG_TC0_CMR0, ACPA,BCPB are set to 3). Here TIOB0 is toggling and I want to stay at one valve (0 or 3.3v) for whole period.
Thanks for your suggestion.
when I have zero in a compare register I expect a zero output
i expect the output to be triggered two times (UP and DOWN) every tick (i think you call it period), because the timer is overflowing EVERY tick.
Solution is turn off the timer comparison.
this seems to me a PWM, maybe you'll get better result using the dedicated HW
Yes what you said is correct. At first I couldn't get it but this MCU timer has option to set or clear the timer output value for whole period. so without going for TOGGLE always, I used these options to get desired operation.

Qt5 QSerialPort write data

How I can write data in serial port, with delay between send's messages?
This is my code:
void MainWindow::on_pushButton_Done_clicked()
{
if(sport->isOpen()){
sport->clear();
QString cmd = Phase+Mode;
//Write Stop
sport->write("stop!", 5);
//Write Mode
sport->write(cmd.toStdString().c_str(), cmd.toStdString().length());
//Write Speed
sport->write(Speed.toStdString().c_str(), Speed.toStdString().length());
//Write Direction
sport->write(Direction.toStdString().c_str(), Direction.toStdString().length());
//Run
sport->write("start!", 6);
}
}
My device receives an error message when I call this function.
Thank you.
2 options:
use waitForBytesWritten to ensure the bytes are written and then a short sleep
however this will block the thread and will block the gui
the other is using a QTimer to trigger another slot a few times and a field that will indicate what needs to be sent
Looks like you are trying to program some step motor controller or something similar.
Usually in such controllers you should wait for controller response to verify that command was processed properly.
It looks like that your design of code is very bad. Move everything related with this controller to separate class, which has set of slots, something like: starRotateLeftWithSpeed(double). Code will be cleaner and it will be easy to use thread if you decide to use methods like waitForBytesWritten proposed in another answer.
Definitely you should read controller manual more carefully.

Qt show change immediately

I get continuous answers from a server with a delay from 1 sec. I append() this answers to an QTextEdit field. But the changes first displayed when the method call has finished.
How can I displayed the changes immediately?
I have tryed update() but it doesent work..
void ClientWidget::setAnswer(ValueStream *resultStream){
std::vector<std::string> answer;
for(int i = 0; i < 15; i++){
value tmpResultValue;
if(resultStream->get(tmpResultValue)){
this->client.parseResult(tmpResultValue, answer);
std::vector<QString> qAnswer = vectorStringToVectorQstring(answer);
for (unsigned int n = 0; n < qAnswer.size(); n++){
this->answerTextEdit->append(qAnswer[n]);
}
this->answerTextEdit->update();
}
answer.clear();
}
resultStream->close();
delete resultStream;
}
after this->answerTextEdit->append(qAnswer[n]); the changes should displayed but they dont displayed immediately
When you set the TextEdit widget's text, a signal is emitted that it has changed, in order for the widget to update what you see. That signal is placed in a queue of messages that are processed as events in the Qt event loop.
While you're processing the incoming data, Qt's event loop cannot continue until you finish. An easy, but not the best way of handling this is to call QApplication::processEvents to allow the event loop to run; this can be very inefficient as all events in the queue are processed.
A better way to handle time-consuming processing is to move it onto a new thread, which is reasonably easy to do with QThread. That way, you can process the incoming requests from the server and emit a signal from your thread to the main thread, which can then update the TextEdit widget.
To understand how to use QThread, I suggest reading this article. It really isn't difficult to do and I recommend you try it, rather than adding a call to QApplication::processEvents.
You can call
QApplication::processEvents();
after calling your method.
if you can change ValueStream to emit a signal each time a new value is available with the value as a parameter, then it will become much easier. just connect a slot to it where you append the answer to the answerTextEdit

Replacement for Arduinos millis() that is reliable also with disabled interrupts

As stated in stackoverflow-17135805 the millis() function does not return the correct time, if the interrupts where disabled, while Arduino had to detect an overflow of timer0.
I have a time critical program that uses a lot of functions which have to disable the interrupts. So my program runs 1:30 while it thinks it was running only for 1:00.
Is there another timer that I can use to avoid this problem?
It happens to me when I use the GSM Module:
// startpoint
unsigned long t = 0;
unsigned long start = millis();
while ( (millis()-start) < 30000 ){
//read a chunk from the gprs module
for (int i=0;i<8;i++)
client.read();
//do this loop every 10ms
while( (millis()-start) < t*10 ){};
t++;
}
//endpoint
From the startpoint to the endpoint it should take 30 seconds. Instead it takes 65 seconds.
If you have to disable interrupts so often and so long your best bet would be to use an external timer. I highly recommend DS3231. Since it has a build in crystal it is easier to setup than a 1307 and it is also significantly more accurate.
You could use one of the other hardware timers
to keep track of the time. For example, on the Leonardo Timer 1 is a 16 bit timer.
To set it up directly (this obliterates code portability) there are a couple steps.
TCCR1A = 0;
this puts the timer in "normal" mode, meaning it just runs to 0xFFFF and wraps back to 0x0000.
TCCR3B = 0;
TCCR3B = _BV(CS11) | _BV(CS10);
this starts the timer and sets it to use a clock/64 prescale, which equates to 1 tic every 4us.
To check the time:
long time; // declared somewhere in scope.
time = TCNT1; // this reads the timer count register
time *= 4; // this multiplies time by 4 to give you us.
As mentioned earlier, TCNT1 wraps around at 0xFFFF = 65536. So, with the pre-scaler set as above, that gives you about 65536 * 4E-6 = .262 seconds of counting before your program needs to put the data into a bigger variable (assuming you care). Hopefully it isn't a problem to poll things more often than 4 times a second, which gets you away from interrupts.
Several arduino core functions utilize these timers, so you'll need to verify that the core functions you need don't depend on the timer you choose. For example, doing the above will break analogWrite() on certain pins.

heap memory release policy in Arduino

#include <Arduino.h>
#include "include/MainComponent.h"
/*
 Turns on an LED on for one second, then off for one second, repeatedly.
*/
MainComponent* mainComponent;
void setup()
{
   mainComponent = new MainComponent();
   mainComponent->beginComponent();
}
void loop()
{
   mainComponent->runComponent();
}
is there any callback to release memory in Arduino ?(e.g to call delete mainComponent)
or this will happen automatically as the loop ends?
what is the strategy to ensure freeing the memory allocated in that code snippet?
SCENARIO :"I wanted to access the object in both methods , so the  object is declared in the global scope then instantiated at setup."
What happen when loop() terminated ? will  mainComponent still remain in the memory?
If it was in OS NO , process will terminated then resources will be deallocated.
So in Arduino how can I achieve above SCENARIO , by ensuring memory will be deallocated when the controller is switched off ?
What is confusing you is that the main() function is hidden by the basic Arduino IDE. Your programs have a main() function just like on any other platform, and have a lifecycle same as when run on a computer with OS. If you look under arduino___\hardware\cores\aduino, you will find a file main.cpp, which is included into your binaries:
int main(void)
{
init();
//...
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
Considering this file you will now see, that while you exit the loop(), it is continuously called. Your program never exits. In general, your best pattern is to new objects once and never delete, like you have done here. If you are new'ing and delete'ing objects repeatedly on a microcontroller, you are not thinking about lifecycles and resources wisely.
So
"is the new'd object deleted at return from loop()?" No, the program is still running and it stays on the heap.
"What happens at power off? Is there a way to clean up?" The moment the supply voltage drops too low, the microcontroller will stop executing instructions. Power supervisor circuitry prevents the controller from doing anything erratic as the voltage drops (should prevent) When the voltage is conpletely drained, all the RAM is lost. Without adding circuitry, you have no way to execute any clean up at power off.
"Do I need to clean up?" No, at power up, everything is reset to a known state. Operation cannot be affected by anything left behind in RAM (presumes you initialize all your variables).

Resources