Skip to content

Intarzieri fara blocare in Arduino, si comparatii cu LunaAVR

Aprilie 18, 2014

Se da urmatoarea sarcina: clipirea simultana a trei LED-uri la frecvente diferite: 250ms, 500ms, 760ms. Unul dintre LED-uri va fi cel inclus pe placa Arduino. Celelalte doua le montam pe un „breadboard” si le conectam la D7 si D6.

arduino-delay-noblocking

In Wiring language, programul arata ca mai jos:

const int ledPin =  13;      // the number of the LED pin
const int ledPin2 =  7;      // the number of the LED2 pin
const int ledPin3 =  6;      // the number of the LED3 pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
int ledState2 = LOW;             // ledState used to set the LED2
int ledState3 = LOW;             // ledState used to set the LED3
long previousMillis = 0;        // will store last time LED was updated
long previousMillis2 = 0;        // will store last time LED2 was updated
long previousMillis3 = 0;        // will store last time LED3 was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 250;           // interval at which to blink (milliseconds)
long interval2 = 500;           // interval at which to blink (milliseconds)
long interval3 = 750;           // interval at which to blink (milliseconds)

void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
}

void loop()
{
// here is where you'd put code that needs to be running all the time.

// check to see if it's time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;

// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
if(currentMillis - previousMillis2 > interval2) {
// save the last time you blinked the LED
previousMillis2 = currentMillis;

// if the LED is off turn it on and vice-versa:
if (ledState2 == LOW)
ledState2 = HIGH;
else
ledState2 = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin2, ledState2);
}
if(currentMillis - previousMillis3 > interval3) {
// save the last time you blinked the LED
previousMillis3 = currentMillis;

// if the LED is off turn it on and vice-versa:
if (ledState3 == LOW)
ledState3 = HIGH;
else
ledState3 = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin3, ledState3);
}
}

Dimensiunea codului este de 1282 bytes.

In LunaAVR, folosim functiile clasei TaskTimer impreuna cu timer0 (avantajul fata de Arduino este ca putem folosi oricare dintre timer-ele aflate la dispozitie, timer0, timer1, timer2). Codul arata ca mai jos:

#library "Library/TaskTimer.interface"

const F_CPU = 16000000
avr.device = atmega328p
avr.clock = F_CPU
avr.stack = 32

#define LED1 as PortB.5
#define LED2 as PortD.7
#define LED3 as PortD.6

LED1.mode = output,low
LED2.mode = output,low
LED3.mode = output,low

#define BASE_FREQ as 1   'ms
#define TASK1_TIME as 250
#define TASK2_TIME as 500
#define TASK3_TIME as 750

dim task1cnt,task2cnt,task3cnt as int16

TaskTimer.SaveMode = nosave
TaskTimer.Init(Timer0,1,BASE_FREQ)
TaskTimer.Task(0) = taskclock().Addr

avr.Interrupts.Enable

do
if task1cnt=TASK1_TIME then
LED1.toggle
clr task1cnt
endif
if task2cnt=TASK2_TIME then
LED2.toggle
clr task2cnt
endif
if task3cnt=TASK3_TIME then
LED3.toggle
clr task3cnt
endif
loop

procedure taskclock()
asm ' save registers
push _LA0
xIn _LA0,SREG
PushA1
PushZ
endasm
task1cnt++
task2cnt++
task3cnt++
asm ' restore registers
PopZ
PopA1
xOut   SREG,_LA0
pop    _LA0
endasm
endproc

Dimensiunea codului este de 499 bytes (cu tot cu stack-ul de 32 bytes care poate lipsi).

Daca renuntam la clasa TaskTimer si folosim doar clasa Timer0 (clasa ce manipuleaza ceasul timer0), atunci obtinem un cod si mai mic.

const F_CPU = 16000000
avr.device = atmega328p
avr.clock  = F_CPU
avr.stack = 8

#define LED1   as PortB.5
#define LED2   as PortD.7
#define LED3   as PortD.6

LED1.mode   = output,low
LED2.mode   = output,low
LED3.mode   = output,low

#define BASE_FREQ   as 1   'ms
#define TASK1_TIME   as 250
#define TASK2_TIME   as 500
#define TASK3_TIME   as 750

dim task1cnt,task2cnt,task3cnt as word

const TIMER_PRESCALE   = 1024
const TIMER_PRELOAD      = 256 - word((F_CPU / TIMER_PRESCALE /(1000 / BASE_FREQ) + 0.5))

timer0.Clock = TIMER_PRESCALE
timer0.Value = TIMER_PRELOAD
timer0.isr = delaytask
timer0.Enable

avr.Interrupts.Enable

do
if task1cnt=TASK1_TIME then
LED1.toggle
clr task1cnt
end if
if task2cnt=TASK2_TIME then
LED2.toggle
clr task2cnt
end if
if task3cnt=TASK3_TIME then
LED3.toggle
clr task3cnt
end if
loop

isr delaytask nosave
asm
push   _LA0
xIn      _LA0,SREG
PushA1
PushZ
endasm
timer0.value = TIMER_PRELOAD
task1cnt++
task2cnt++
task3cnt++
asm
PopZ
PopA1
xOut   SREG,_LA0
pop      _LA0
endasm
endisr

Dimensiunea codului este de 382 bytes.  Conteaza? Numai pentru aceasta aplicatie desigur ca nu conteaza atata vreme cat irosim o placa Arduino. Insa acest cod se poate compila pentru cel mai mic ATtiny care indeplineste cerintele programului.  Aproape intotdeauna, cod mai mic inseamna controler mai mic si mai ieftin.

Sursa.

Lasă un comentariu

Va rog, nu folositi limbaj de messenger. Multumesc!

Completează mai jos detaliile despre tine sau dă clic pe un icon pentru autentificare:

Logo WordPress.com

Comentezi folosind contul tău WordPress.com. Dezautentificare / Schimbă )

Poză Twitter

Comentezi folosind contul tău Twitter. Dezautentificare / Schimbă )

Fotografie Facebook

Comentezi folosind contul tău Facebook. Dezautentificare / Schimbă )

Fotografie Google+

Comentezi folosind contul tău Google+. Dezautentificare / Schimbă )

Conectare la %s

%d blogeri au apreciat asta: