40.8.12.1. Heartbeat

Odkazy:

Heart beat je technologie práce s LED diodou, kdy poblikáváním této diody dává zařízení najevo, že je v pořádku.

Můžeme samozřejmě obyčejně blikat led, ale často potřebujeme lepší efekt než pouhé blikání, a navíc toto musíme zaintegrovat do aplikace. Inspirován podobnou funkcí v 40.8.10.1 – „Arduino AVR ISP programátor“ a ... jsem se rozhodl vyřešit problém trochu jinak. Výchozí myšlenka je že chci aby se jas LED diody měnil podel funkce sin, případně podle jiné. Další podmínkou je, že si funkce sama musí hlídat čas a nemá tedy používat delay. Přišel jsem s řešením, kdy hodnoty funkce jasu je uložena v poli heartbeat_array. To mi dovolí si předem připravit libovolnou funkci a v průběhu volání heartbeat jinž neztrácím čast výpočty v plovoucí řádové čárce. Dalším prvkem řešení je hlídání času. Funkce ji třeba volat rozumě často a ona sama rozhodně jestli již uběhl požadovaný čas STEP.

#define STEP 50

unsigned long lastTime;
uint8_t heartbeat_array[] = {
#include "sintable.h"
};

void heartbeat(int led) {
	unsigned long now = millis();
	static uint8_t table_index=0;

	/* Check if time is enough, return else */
	if (now < lastTime + STEP) {
		return;
	}
  
	analogWrite(led, heartbeat_array[table_index++]);
	if (table_index >= sizeof(heartbeat_array)) {
		table_index = 0;
	}
	lastTime += STEP;
}

Hodnoty pole heartbeat_arra vytvářím krátkým programem v Ruby. Jednoduchou úpravou kdy se funkce sin zamění za jinou, dosáhneme požadovaného průběhu.

#!/usr/bin/env ruby
# This program creates table of output signal for function heart beat.

def generate_table steps, minvalue, maxvalue
  puts "/*
 * Sin x-PI/2 table in #{steps} steps with minumum at #{minvalue} and maximum at #{maxvalue}.
 * Generated with commad:
 * ./generate_table #{steps} #{minvalue} #{maxvalue}
 */"

  puts (0..steps-1) \
    .collect{|deg| (deg.to_f * 2.0 * Math::PI) /steps} \
    .collect{|r| (Math::sin(r - Math::PI/2)+1)/2 * (maxvalue-minvalue) +minvalue} \
    .collect{|n| "%3d" % n.round} \
    .each_slice(8).collect{ |row| "\t" + row.join(', ') }.join ",\n"
end

if $0 == __FILE__ then
  generate_table ARGV[0].to_i, ARGV[1].to_i, ARGV[2].to_i
end

Poznámka

Pokud nebude funkce heartbeat volána dostatečně často, vznikne rozdíl v čas lastTime a aktuálním čase. To způsobý zrychlené "dohánění" času.

Bylo by hezké, kdyby buďto sama funkce poznala že nebyla dlouhý čas volána a toto ošetřila.

Bylo by hezké kdybych vyřešil náběh LED z nuly při prvním cyklu, případně doběh po posledním cyklu. Klidová poloha by nemusela být nula ale plný jas.

Licence Creative Commons
Elektronika a počítače, jejímž autorem je Radek Hnilica, podléhá licenci Creative Commons Uveďte autora-Nevyužívejte dílo komerčně-Zachovejte licenci 3.0 Česká republika .