Reputation: 19
I got the problem, that the following code ain't multitasked. How can I realize that? My code works at the moment as follow: I start my Android app, there I confirm the USB request. After the press of the "start button", my app sends a byte array to my arduino board. The problem is that "stepper2(ingredient1value);" can only start when "stepper1..." finished.
I know that arduino ain't the right plattform for multithreading, but I saw some solutions, but I can't integrated them into my code.
Thanks for helping me!
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>
#define VALUE_OFF 0x0
#define VALUE_ON 0x1
#define COMMAND_LED 0x2
#define TARGET_PIN_12 0x12
int stepperPin1 = 9;
int stepperPin2 = 10;
int stepperPin3 = 11;
int stepperPin4 = 12;
int stepperPin5 = 13;
//change this to the number of steps on your motor
#define STEPS 48
AndroidAccessory acc("Manufacturer", "Model", "Description", "1.0", "URI","Serial");
byte ingredient1value, ingredient2value, ingredient3value, ingredient4value, ingredient5value;
byte rcvmsg[8];
void setup() {
Serial.begin(115200);
pinMode(stepperPin1, OUTPUT);
pinMode(stepperPin2, OUTPUT);
pinMode(stepperPin3, OUTPUT);
pinMode(stepperPin4, OUTPUT);
pinMode(stepperPin5, OUTPUT);
acc.powerOn();
}
void stepper1(int turns1){
for(int i=0;i<turns1*STEPS;i++){
digitalWrite(stepperPin1, HIGH);
delayMicroseconds(800);
digitalWrite(stepperPin1, LOW);
delayMicroseconds(800);
}
}
void stepper2(int turns2){
for(int i=0;i<turns2*STEPS;i++){
digitalWrite(stepperPin2, HIGH);
delayMicroseconds(800);
digitalWrite(stepperPin2, LOW);
delayMicroseconds(800);
}
}
void stepper3(int turns3){
for(int i=0;i<turns3*STEPS;i++){
digitalWrite(stepperPin3, HIGH);
delayMicroseconds(800);
digitalWrite(stepperPin3, LOW);
delayMicroseconds(800);
}
}
void stepper4(int turns4){
for(int i=0;i<turns4*STEPS;i++){
digitalWrite(stepperPin4, HIGH);
delayMicroseconds(800);
digitalWrite(stepperPin4, LOW);
delayMicroseconds(800);
}
}
void stepper5(int turns5){
for(int i=0;i<turns5;i++){
digitalWrite(stepperPin5, HIGH);
delay(1000);
digitalWrite(stepperPin5, LOW);
delay(1000);
}
}
void loop() {
delay(50);
if (acc.isConnected()) {
acc.read(rcvmsg, sizeof(rcvmsg), 1);
if (rcvmsg[0] == COMMAND_LED && rcvmsg[1] == TARGET_PIN_12) {
byte value = rcvmsg[2];
if (value == VALUE_ON){
ingredient1value=rcvmsg[3] ;
ingredient2value=rcvmsg[4] ;
ingredient3value=rcvmsg[5] ;
ingredient4value=rcvmsg[6] ;
ingredient5value=rcvmsg[7] ;
stepper1(ingredient1value);
stepper2(ingredient2value);
stepper3(ingredient3value);
stepper4(ingredient4value);
stepper5(5);
}
}
}
}
Upvotes: 0
Views: 1029
Reputation: 654
Basically answer by user3704293 is correct:
For each action you want to perform regularly, create a variable that holds the interval between actions, in milliseconds.
Create a second variable that will hold the time, when it was last triggered.
However this naive algorithm with fail if Arduino is left running for more than a month. The millis();
function will reach maximum value in roughly 50 days, and rollover back to zero. Once that happens, you code will no longer trigger.
Please look into this guide on arduino playground, it's the cause of much confusion for many hobbyists. It probably won't matter for your project, but it may for others.
If your project gets more complicated, it would benefit from having a Real scheduler, instead of having you reinvent the wheel. It's like a small operating system that manages several tasks for you. Some are available as Arduino libraries. DuinOS is a good one to look at, it's based on FreeRTOS - very popular, you will see it everywhere. If you learn how to use it, that would serve you well in the future. If you are short on program memory, use Protothreads instead. There are other alternatives, but these are good places to start.
Finally if you need scheduling on a calendar date, you would need to connect a Real Time Clock, take a look at the Time library
Upvotes: 1
Reputation: 1056
One approach could be to avoid delay()
(or delayMicroseconds()
) in your code and replace these code passages with code patterns, which does not interrupt the main loop and allow the Arduino to execute commands in specific frequencies or times.
Here is an example how you can execute a function every second without using delay()
(and without block other commands, which should be executed with a higher frequency):
// 1 sec. frequency
unsigned long interval=1000; // the time we need to wait
unsigned long previousMillis=0; // millis() returns an unsigned long.
// 3 sec. frequency
unsigned long interval1=3000; // the time we need to wait
unsigned long previousMillis1=0; // millis() returns an unsigned long.
void setup() {
//...
}
void loop() {
if ((unsigned long)(millis() - previousMillis) >= interval) {
previousMillis = millis();
// every second
// ...
}
if ((unsigned long)(millis() - previousMillis1) >= interval1) {
previousMillis1 = millis();
// every third second
// ...
}
// other CMD's...
}
EDIT:
This approach does not integrate a real multi-task, but gives you the possibility to integrate a pseudo-parallelism in your project.
I added a second condition (execution every third second)to exemplify the principle.
Upvotes: 2