Jeffrey Cross
Jeffrey Cross

Výpis Arduino Cookbook: Velké tabulky dat v paměti programu

Pokud jste někdy vytvořili projekt založený na technologii Arduino s velkým množstvím textových řetězců, rychle zjistíte, že standardní vydání Ardamova 2K SRAM je velmi omezující. Jedním z řešení je místo toho uložit text do paměti programu, což je o 32Kb mnohem více.

Na jaře roku 2011 jsem pracovala na projektu s umělci Stevem Hansonem a Elliotem Clappem, který byl součástí skupiny Apexart's "Let it end like this". Steve vytvořil generativní dotazník, který dotazoval návštěvníky galerií a představil jim jejich poslední slova. Interaktivní tlačítková konzola a LCD displej byl postaven firmou Elliot (na obrázku nahoře) a postavili jsme to pomocí levné varianty Arduino z Modern Device. Celý projekt je dokumentován v wiki projektu: Projekty.

Stevovo básnické Poslední slovo zabralo téměř 16 K paměti, která byla uložena v paměti programu Arduina. Níže je výňatek z Arduino Cookbook od Michaela Margolisa, který vysvětluje, jak uložit a získat přístup k velké tabulce dat v paměti programu.

17.3 Ukládání a načítání číselných hodnot v paměti programu

Problém

Máte spoustu konstantních číselných údajů a nechcete to přidělit RAM.

Řešení

Uložte numerické proměnné do paměti programu (paměť flash slouží k ukládání programů Arduino).

Tento náčrt upravuje blikající LED pro nelineární citlivost lidského vidění. Ukládá hodnoty, které mají být použity v tabulce 256 hodnot v paměti programu, nikoli v paměti RAM.

Náčrt je založen na Recipe 7.2; viz kapitola 7 pro schéma zapojení a diskusi o LED diodách řízení. Výsledkem tohoto náčrtu je hladká změna jasu pomocí LED na pinu 5 ve srovnání s LED na pinu 3:

/ * ProgmemCurve sketch * používá tabulku v Progmemu k převodu lineárního na exponenciální výstup * Viz Recipe 7.2 a Obrázek 7-2 * / #include // potřebné pro PROGMEM // tabulku exponenciálních hodnot // generovaných pro hodnoty i od 0 do 255 -> x = round (pow (2,0, i / 32,0) - 1); konstantní bajtová tabulka [] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, 58, 59, 60, 62, 63, 64, 66, 67, 69, 70, 72, 73, 75, 77, 78, 80, 82, 84, 86, 88, 90, 91, 94, 96, 98, 100, 102, 104, 107, 109, 111, 114, 116, 119, 122, 124, 127, 130, 133, 136, 139, 142, 145, 148, 151, 155, 158, 161, 165, 169, 172, 176, 180, 184, 188, 192, 196, 201, 205, 210, 214, 219, 224, 229, 234, 239, 244, 250}; const int rawLedPin = 3; // tato LED dioda je napájena syrovými hodnotami const int modifiedLedPin = 5; // tato LED je řízena z tabulky int jasu = 0; int přírůstek = 1; void setup () {// piny řízené analogWrite nemusí být deklarovány jako výstupy} void loop () {if (brightness> 254) {inkrement = -1; // odpočítat po dosažení 255} jinak pokud (jas <1) {inkrement = 1; // spočítat po poklesu zpět na 0} jas = jas + přírůstek; // přírůstek (nebo znaménko snížení je mínus) // zapíše hodnotu jasu na LED diody analogWrite (rawLedPin, jas); // toto je surová hodnota int adjustBrightness = pgm_read_byte (& table [brightness]); // upravená hodnota analogWrite (adjustedLedPin, adjustBrightness); zpoždění (10); // 10ms pro každou změnu kroku znamená 2,55 sekundy pro zeslabení nahoru nebo dolů}

Diskuse

Pokud potřebujete pro výpočet rozsahu hodnot, které se pravidelně opakují, použít komplexní výraz, je často lepší předpočítat hodnoty a zahrnout je do tabulky hodnot (obvykle jako pole) v kódu. Tím se ušetří čas potřebný k opakovanému výpočtu hodnot při spuštění kódu. Nevýhodou je paměť potřebná k umístění těchto hodnot do paměti RAM. RAM je omezena na Arduino a mnohem větší prostor pro programovou paměť lze použít pro ukládání konstantních hodnot. To je užitečné zejména pro skici, které mají velká pole čísel.

V horní části náčrtu je tabulka definována následujícím výrazem:

const byte table [] PROGMEM = {0,. . .

PROGMEM řekne kompilátoru, že hodnoty mají být uloženy v paměti programu, nikoli v RAM. Zbytek výrazu je podobný definování konvenčního pole (viz kapitola 2).

Definice nízkých úrovní potřebné k použití PROGMEM jsou obsaženy v souboru s názvem pgmspace.h a skica obsahuje následující postup:

#zahrnout

Chcete-li nastavit jas tak, aby fade vypadal rovnoměrně, tento recept přidává následující řádky do výstupního kódu LED použitého v Recipe 7.2:

int adjustBrightness = pgm_read_byte (& tabulka [jas]); analogWrite (adjustedLedPin, adjustBrightness);

Proměnná adjustBrightness se nastavuje z hodnoty přečtené z paměti programu. Výraz pgm_read_byte (& tabulka [jas]); znamená vrátit adresu záznamu v poli tabulky v pozici indexu dané jasem. Každá položka v tabulce je jeden bajt, takže další způsob psaní tohoto výrazu je:

pgm_read_byte (tabulka + jas);

Pokud není jasné, proč a tabulka [jas] odpovídá tabulce + jasu, nebojte se; použijte jakýkoliv výraz, který vám dává větší smysl.

Dalším příkladem je Recipe 6.5, který používal tabulku pro převod infračerveného čidla na vzdálenost. Zde je náčrt z tohoto receptu převedený na použití tabulky v paměti programu místo RAM:

/ * ir-distance_Progmem skica * tisk vzdálenosti a změny Rychlost záblesku LED * v závislosti na vzdálenosti od IR snímače * používá progmem pro tabulku * / #include // potřebné při použití položek tabulky Progmem // jsou vzdálenosti v krocích po 250 milivoltech const int TABLE_ENTRIES = 12; const int firstElement = 250; // první záznam je 250 mV const int interval = 250; // millivolts mezi každým prvkem // následuje definice tabulky v programové paměti const int distanceP [TABLE_ENTRIES] PROGMEM = {150,140,130,100,60,50, 40,35,30,25,20,15}; // Tato funkce čte z paměti programu v daném indexu int getTableEntry (int index) {int value = pgm_read_word (& distanceP [index]); návratová hodnota; }

Zbývající kód je podobný Recipe 6.5, kromě toho, že funkce getTableEntry se používá k získání hodnoty z paměti programu namísto přístupu k tabulce v RAM. Zde je revidovaná funkce getDistance z tohoto receptu:

int getDistance (int mV) {if (mV> interval * TABLE_ENTRIES) vrátí getTableEntry (TABLE_ENTRIES-1); // minimální vzdálenost {int index = mV / interval; float frac = (mV% 250) / (float) interval; return getTableEntry (index) - ((getTableEntry (index) - getTableEntry (index + 1)) * frac); }}


V hale Maker:

Arduino Cookbook Vytvořte si vlastní roboty, hračky, dálkové ovladače, alarmy, detektory a další s Arduino a tímto průvodcem. Arduino umožňuje umělcům a designérům vytvářet různé úžasné objekty a prototypy, které působí na fyzický svět. S touto kuchařskou knížkou se můžete potápět a experimentovat, a to díky více než sto tipům a technikám, bez ohledu na úroveň vašich dovedností. Zde naleznete příklady a rady, které potřebujete k zahájení, rozšíření a zdokonalení vašich projektů.

Podíl

Zanechat Komentář