I've got a 1284P Arduino compatible microcontroller running my sketch connected to a TFT capacitive touch LCD screen.
The microcontroller is also attached to Bluetooth and Wi-Fi modules.
All is great but the microcontroller is only running at 16MHz which is causing some constraints and work arounds in my design.
When a touch is made on the LCD an interrupt is sent however I can't detect the position of the touch within the interrupt and must be done from the main loop. So a flag must be set which is then conditioned in the main loop at points where communication is made between my external modules and time is spent in program execution. I condition this flag from the interrupt at these points and if true then it bails on whatever it was doing. All these loops bail and return to the top of the main loop where the position of the touch can be found and action is taken.
However.. The time taken from the touch up until the touch position is found and action taken is too slow for a usable device.
Increasing the CPU speed would eliminate the problem but that's not an option in this case.
What are my options? At the moment I'm just doing all I can within my interrupt in terms of writing to the screen but anything more intensive a flag is set within the interrupt then in the main loop its conditioned and if found true locks itself into a while loop where all processing power is on a particular intensive task listening for the users touch positions very closely. This means I can't do anything else such as interface with the modules as I'm constantly listening to the users touch.
Could I not have Goto statements within points of my code that takes time to execute and once a flag is set in the interrupt routine from the touch a goto statement is trigged at one of these points which takes it right to code that checks the position of the touch and takes action? From my main loop I have many functions spanning out, can goto statements be used in this case?
I'd love some insights or experience on this matter. I've just got to make the most of what I've got.
Could I not have Goto statements within points of my code that takes time to execute and once a flag is set in the interrupt routine from the touch a goto statement is trigged at one of these points which takes it right to code that checks the position of the touch and takes action?
How about calling a function that executes the appropriate code instead of using a (nasty) goto to get to it ?
marco_c:
16MHz is a lot of processing power for the tasks you have outlined.
Maybe post your code?
My code is split into three pages for the mail loop, Wi-Fi and Display and is too lengthy to post.
In short, the device has to poll my server every 10 seconds or so and the process of interfacing with my Wi-Fi module to push a request to my server takes a few seconds on the Wi-Fi modules end which is something out of my control. Then I parse the response and draw it to the display with graphics which again takes a second or so.
When I get a touch a flag is set through an interrupt rutien and then this flag needs to be polled to escape to the main loop. The time it takes to escape is too slow to get a instant response with a touch for example a play/pause button.
So could I use a Goto statement in this case? I've tried to use them however I get an error saying the label is undefined in the function, how do I define it within, is it possible?
Sounds to me like you have a poor architecture, and you're tying up the CPU doing long tasks that should be broken up into smaller tasks, to make the UI more responsive. 16MHz is pretty darned fast, and can do a HUGE amount of work with well-written code. If you want your code to work as it should, you'll have to post it, so people can point out what you're doing wrong.
and the process of interfacing with my Wi-Fi module to push a request to my server takes a few seconds on the Wi-Fi modules end which is something out of my control.
This seems like an entirely unbelievable claim. And even if it was true, how would either a faster clock speed, or a goto statement, actually help ?
Looking back and thinking about it you are right in saying its an outrageous claim.
I was going down the completely wrong route and it was UKHeliBob answer that helped me understand.
He said,
"How about calling a function that executes the appropriate code instead of using a (nasty) goto to get to it ?"
It was there right in my face, why didn't I do it, I don't know.
I've got a function that handles all touches and is called at critical points in my code such as functions that read data from my modules. The function is called at these points when a flag is set from my interrupt routine.
I was going down the route of keeping my touch handler code static in the main loop and having everything come to it rather then just putting it in a function and calling it.
Stupid mistake but wow I can really utilize its power now, you've all really made me understand the power of 16MHz!
If your wifi really takes several seconds to work, is this because you have to power it up every time you want to send a message ? Unless you have some critical battery life issue, can you leave it powered up ?
And, if your wifi really takes several seconds to work, are you using a scheme where you send a message, and then wait ( with your arduino unable to do anything else ) for a response ? Is there some other arrangement you can use, where you send the message, and can then do other things, and when the response arrives several seconds later, you can detect that either will an interrupt, or by frequently checking the device status ?
michinyon:
If your wifi really takes several seconds to work, is this because you have to power it up every time you want to send a message ? Unless you have some critical battery life issue, can you leave it powered up ?
And, if your wifi really takes several seconds to work, are you using a scheme where you send a message, and then wait ( with your arduino unable to do anything else ) for a response ? Is there some other arrangement you can use, where you send the message, and can then do other things, and when the response arrives several seconds later, you can detect that either will an interrupt, or by frequently checking the device status ?
I'm using an ESP8266 Wi-Fi module and communicate through AT commands. Sending commands to connect to my server and then HTTP requests takes a few seconds to get a response. Some of that time could be on my server end as it generates the response from retrieving data from multiple API's.
Here's my function for sending data to my Wi-FI module. I have a timeout which would be 5 seconds or so which means if no data is received in those 5 seconds then it bails. During these five seconds I can do other things and checks such as check for touches as shown in my function. If the data is received from the module and its the correct response then the data is returned straight away.
/**
* Allows communication with the ESP8266 Wi-Fi Module by sending commands and checking for a response
* @param command - Command to sent to Wi-Fi module (e.g "AT+RST")
* @param timeout - Max time looking for response (e.g. 5)
* @param checkForResponse - If to check for response or not (e.g. true)
* @param responseKey - The response you are expecting (e.g. "OK")
* @param responseKeySize - The size of the response key (e.g. 2)
* @return boolean - status of request, true if response was found, false if timeout was exceeded
*/
boolean sendData(char* command, const int timeout, const boolean checkForResponse, char* responseKey, byte responseKeySize)
{
// Response array variables
int ndx = 0;
char rc = (char)0;
// Clear response buffer
memset(wifiResponseBuffer, 0, sizeof(wifiResponseBuffer));
// Debug
if(DEBUG) {
//Serial.println("WiFi/sendData():: command : " + String(command));
}
// Send command to Wi-Fi module
Serial1.print(command);
// Flag to define if new data has been received
boolean newData = false;
// Record current time for timeout
long int time = millis();
// Timeout | Only check for new data while still inside the defined timeout in miliseconds
while((millis() - time < timeout))
{
// If screen is touched
if(screenTouched) {
if(DEBUG) Serial.println("Wi-Fi/sendData():: Touch found executing touchHandler()");
touchHandler();
}
// If there is new data from the Wi-Fi module
while(Serial1.available() > 0)
{
// Read and save as a char
rc = Serial1.read();
// Save and increment response buffer
wifiResponseBuffer[ndx] = rc;
ndx++;
// Set new data flag | new data has arrivied
newData = true;
}
// If new data has been received | Check for response flag must be set
if(newData && checkForResponse) {
// Null terminate the buffer | Add null char to the end
wifiResponseBuffer[ndx] = '\0';
// Check if response key word is at the end of the response buffers data
if(strcmp(&wifiResponseBuffer[strlen(wifiResponseBuffer)-responseKeySize], responseKey) == 0) {
// Debug
if(DEBUG) {
/*
Serial.println(F("WiFi/sendData():: Response has been found in responseBuffer :"));
Serial.println(LINEBREAK_STAR);
Serial.println(wifiResponseBuffer);
Serial.println(LINEBREAK_STAR);
*/
}
// Response has been found | Return so no time is waisted looking for more data
return true;
} else {
// Remove null termination
wifiResponseBuffer[ndx] = ' ';
// New data has been searched | Set flag so loop will look for more data
newData = false;
}
}
}
// Debug
if(DEBUG) {
Serial.println(F("WiFi/sendData():: Timeout was exceeded in responseBuffer : "));
Serial.println(LINEBREAK_STAR);
Serial.println(wifiResponseBuffer);
Serial.println(LINEBREAK_STAR);
}
// Timeout was exceeded
return false;
}
Well two things I can see. Your variable for comparison with millis() should be "unsigned long", and you have "long int". However, this might only be an issue when millis() rolls over.
The other problem is, you might respond too early to the first response character you get, instead of waiting for the whole response message to arrive.
// Null terminate the buffer | Add null char to the end
wifiResponseBuffer[ndx] = '\0';
// Check if response key word is at the end of the response buffers data
if(strcmp(&wifiResponseBuffer[strlen(wifiResponseBuffer)-responseKeySize], responseKey) == 0) {
It seems to me, before you attempt to do this bit of the code, you must have received at least responseKeySize characters. If you haven't received that many characters, there is no point in trying to match the key. And you avoid accessing an array at a negative index, which is never a good idea.