Attiny44A Arduino Multitarea

Estoy tratando de hacer parpadear un LED y encender / apagar un motor en paralelo usando attiny44A a continuación es mi código:

Controlador de bomba:

   digitalWrite(pump1, HIGH);
   delay(5000);
   digitalWrite(pump1, LOW);
   digitalWrite(pump2, HIGH);
   delay(5000);

parpadeo llevado:

    digitalWrite(ledB, HIGH);
    delay(500);
    digitalWrite(ledB, LOW);
    delay(500);

¿Cómo hago para que esto funcione en paralelo?

Respuestas (3)

Hay algunas formas de hacerlo, como usar interrupciones de temporizador, etc., pero otra forma es usar una máquina de estado simple para realizar un seguimiento de cuándo ocurrieron los eventos por última vez. Trate esto más como un ejemplo de cómo hacerlo porque no está probado y no soy un usuario de Arduino, por lo que puede tener algunos tipos de datos incorrectos. Pero un enfoque sería algo como:

boolean led_on = false;
unsigned long led_toggle_ms = 0;
boolean pump1_on = false;
unsigned long pump_toggle_ms = 0;

void loop()
{
    if (millis() - led_toggle_ms >= 500)
    {
        led_toggle_ms = millis();
        led_on = !led_on;
        digitalWrite(ledB, led_on);
    }
    if (millis() - pump_toggle_ms >= 5000)
    {
        pump_toggle_ms = millis();
        pump1_on = !pump1_on;
        digitalWrite(pump1, pump1_on);
        digitalWrite(pump2, !pump1_on);
    }
}

Al realizar un seguimiento de la hora en que ocurrió algo por última vez en lugar de usarlo, delaypermite que el resto del código continúe ejecutándose. Tenga en cuenta que, según la documentación de millis(), el valor se desbordará después de aproximadamente 50 días, por lo que si desea que la aplicación se ejecute durante más tiempo, deberá tenerlo en cuenta. Si no le importa una falla momentánea después de 50 días, podría ser algo simple como:

if ((millis() - led_toggle_ms >= 500) || (millis() < led_toggle_ms))

También puede simular algunas tareas paralelas que se ejecutan en algunos intervalos preconfigurados.

Nota: Usé la operación bit a bit directa para controlar el parpadeo del LED, pero puede hacerlo usando, digitalWritepor supuesto

#include <Arduino.h>

//------------------------------------------------------------------------------
// Declarations // should be in the .h file

#define THA 0
void threadA(unsigned long time);

#define THB 1
void threadB(unsigned long time);

#define THC 1
void threadC(unsigned long time);

//------------------------------------------------------------------------------
// Initializations

const unsigned int pump1 = _BV(0);  //0b00000001, bit position, bit 0 in PORTB, == digital pin 9
const unsigned int ledB = _BV(1); //0b00000010, bit position, bit 1 in PORTB, == digital pin 10

// Threads definitions
// You can add or remove threads here
void (*THREADS[])(unsigned long) = {threadA, threadB, threadC};
int THINT[] = {0, 500, 5000}; // Interval for each threads

//------------------------------------------------------------------------------
// Threads

// Main loop, no interval
void threadA(unsigned long time){

}

// Every 500ms
void threadB(unsigned long time){
  PORTB ^= ledB; // Just toggle a led ON/OFF on bit ledB on PORTB
}

// Every 5000ms
void threadC(unsigned long time){
  PORTB ^= pump1; // Toggle the motor
}

//------------------------------------------------------------------------------
// Arduino core

void setup(){
  DDRB |= ledB | pump1; // Enable ledB and pump1 as output
}

// The loop method handle threads by launching each threads one after the other when their time come
void loop(){
  const int nbThread = sizeof(THREADS)/sizeof(&threadA); // Number of threads
  unsigned long threadTime[nbThread];
  char nextThread = 0;

  while(1){
    if((threadTime[nextThread] + THINT[nextThread]) < millis()){
      threadTime[nextThread] = millis();
      (*THREADS[nextThread])(threadTime[nextThread]);
    }

    if(++nextThread >= nbThread)
      nextThread = 0;
  }
}

Hay dos maneras de hacer esto. La manera cruda es reemplazar el

delay(5000);

en el código del controlador de la bomba con 5 veces el código de parpadeo del LED. Crudo, pero funciona. Aunque no muy flexible...

De otra manera es usar interrupciones de temporizador. Básicamente, inicia un temporizador y hace que genere una interrupción a intervalos establecidos. Luego cuenta las interrupciones y cuando alcanza un cierto número de 'pulsos', realiza la acción requerida.

Para hacer esto, debe conocer la velocidad del reloj de su arduiono, configurar los multiplicadores/divisores del temporizador, etc. y crear el código de interrupción apropiado. Esto es demasiado para una respuesta aquí, pero un Google para 'interrupciones del temporizador' debería ayudarlo a comenzar.

Arduino tiene una biblioteca de temporizador: http://playground.arduino.cc/Code/Timer - No estoy seguro de si hay algo similar para ATTiny.