Vítejte na Elektro Bastlírn?
Nuke - Elektro Bastlirna
  Vytvořit účet Hlavní · Fórum · DDump · Profil · Zprávy · Hledat na fóru · Příspěvky na provoz EB

Vlákno na téma KORONAVIRUS - nutná registrace


Nuke - Elektro Bastlirna: Diskuzní fórum

 FAQFAQ   HledatHledat   Uživatelské skupinyUživatelské skupiny   ProfilProfil   Soukromé zprávySoukromé zprávy   PřihlášeníPřihlášení 

Programová záhada
Jdi na stránku 1, 2, 3  Další
 
Přidat nové téma   Zaslat odpověď       Obsah fóra Diskuzní fórum Elektro Bastlírny -> Miniaturní počítače (Arduino, Raspberry a další)
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
Celeron



Založen: Apr 02, 2011
Příspěvky: 17725
Bydliště: Nový Bydžov

PříspěvekZaslal: pá duben 28 2023, 19:39    Předmět: Programová záhada Citovat

Mám tady řídící prográmek na Arduino Pro mini na řízení generátoru Si5351. Zobrazení na OLED 1,3" I₂C, knihovna pro řadič SH1106G.
V Setup mám skok do podprogramu void statup_text(), kterej zobrazí úvodní kecy:
kód:

void statup_text() {                        // úvodní výpis
  display.setTextSize(1);
  display.setCursor(4, 5);
//  display.print("Si5351");
//  display.setCursor(4, 20);
  display.print("VFO / RF Gen");
// display.setCursor(4, 35);
//  display.print("10kHz - 225MHz");
//  display.setCursor(4, 50);
//  display.print("V 14");
  display.display();
  delay(3000);
  display.clearDisplay();

  display.setCursor(4, 5);                  // výpis vstupů
  display.print("Out:");
  display.setCursor(4, 20);
  display.print("CLK0-Adj");
  display.setCursor(4, 35);
  display.print("CLK1-10MHz");
  display.setCursor(4, 50);
  display.print("CLK2-100kHz");
  display.display();
  delay(3000);
  display.clearDisplay();
}

Výpisová prkotina, takhle je to funkční. Ale pokud aktivuju komentovaný řádky, tak se zobrazí "úvodní výpis", pak se počká 3 sekundy, smaže displej, vypíše "výpis vstupů" ale už se neprovede výmaz displeje na konci a zůstane to zakouslý nejspíš v delay(3000).
Když zruším ve Void Setup() skok do Void Startup_text(), tak řízení generátoru za tímhle Startup_textem vše maká jak má.
Ovšem nyní začíná záhada. Pokud jsou odkomentované řádky viz výše, tak se to nekouše. Stačí ale abych jeden výpis přidal a už se to zase kouše. No a nejzajímavější je, že stačí do kódu nahoře přidat do textu pár znaků navíc a zase se to kouše.
Měl jsem podezření, jestli není chyba na nějaký adrese flešky v 328P ale jiná deska to dělá taky. Po kompilaci je ještě 6KB ve flešce volno a proměnný je ještě 1300 byte volno.
Zkusil jsem obsah Void Startup_text zkopírovat do Void Setup() aby se vyloučil problém se zásobníkem a vůbec žádna změna.
Netuším, v čem může být problém. Připadá mi, že pokud se má vypsat víc, než určitej počet znaků, tak se to hryže. Nějaká chyba v knihovně? Divný je, že grafickej test displeje s touhle knihovnou jede bez problémů mimo jiný plnej displej ASCII znaků.

_________________
Jirka

Proč mi nemůže všechno chodit hned ?!!
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Cust



Založen: Jan 17, 2007
Příspěvky: 6296
Bydliště: Husinec-Řež

PříspěvekZaslal: pá duben 28 2023, 19:46    Předmět: Citovat

Mrknul bych se jestli pro tohle nemají knihovny seeeduino. Někde jsem slyšel, že na nejaké OLED měli lepší knihovny...
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail
Celeron



Založen: Apr 02, 2011
Příspěvky: 17725
Bydliště: Nový Bydžov

PříspěvekZaslal: pá duben 28 2023, 21:43    Předmět: Citovat

Jo, o knihovně u8glib od Oli Krause vím, je tam definice pro tenhle řadič:
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); // I2C / TWI
Ale je to monstrum 13KB, co zabere půlku flešky 328P a navíc proti Adafruit OLED knihovnám dost šílený ovládání. Ale v nejhorším zkusím. Díky!

_________________
Jirka

Proč mi nemůže všechno chodit hned ?!!
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
ondraN



Založen: Aug 16, 2022
Příspěvky: 402
Bydliště: Roztoky

PříspěvekZaslal: so duben 29 2023, 6:11    Předmět: Citovat

Já bych řekl, že to je problém s přetečením stacku nebo heapu (podle toho, jak knihovna alokuje paměť). Přesun z jedné funkce do jiné nemá skoro žádný vliv. Protože je práce s řadičem dost pomalá, asi by mohlo pomoci, vložit mezi výpisy menší delay, aby se stihl přesun zchroustaných dat do řadiče. Taky by mohlo pomoci použít ve výpisech makro "F", aby se řetězce ukládaly do flešky a nezabíraly míso v RAMce. Jinak bez možnosti debugování se tenhle problém bude hledat dost blbě.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail
Valdano



Založen: Jan 01, 2023
Příspěvky: 1692
Bydliště: Česká Lípa

PříspěvekZaslal: so duben 29 2023, 20:30    Předmět: Citovat

ondraN napsal(a):
Já bych řekl, že to je problém s přetečením stacku nebo heapu...

Jsem stejného názoru.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Celeron



Založen: Apr 02, 2011
Příspěvky: 17725
Bydliště: Nový Bydžov

PříspěvekZaslal: ne duben 30 2023, 0:45    Předmět: Citovat

Takže se asi zbouchne proti sobě stack, co ukládá směrem dolů a heap, co ukládá směrem nahoru? Nebo datovka vleze do heap?
Jde nějak nastavit velikosti stack a heap?
Koukal jsem na net, co s tím. Vyházet globální definice a nahradit je lokálníma, kouknout jestli int nepůjde předefinovat na char.
Potom jsem ještě četl něco o Static a Dynamic json.Buffer ale vůbec netuším, vo co go.

_________________
Jirka

Proč mi nemůže všechno chodit hned ?!!
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
ondraN



Založen: Aug 16, 2022
Příspěvky: 402
Bydliště: Roztoky

PříspěvekZaslal: ne duben 30 2023, 6:42    Předmět: Citovat

Můžeš si to představit tak, že dolní oblast RAM je alokována pro globální proměnné a její velikost se určí v okamžiku překladu a je neměnná. Nad ní začíná heap, ze kterého se přiděluje RAM dynamicky za chodu ,třeba funkcí malloc, new, a přiděluje se taky proměnným v nově vytvářených objektech. Stack začíná úplně nahoře a jede směrem dolů. Přes něj se předávají data při volání funkcí a vytvářejí se jejich lokální proměnné. Taky na rozdíl od heapu, má stack hardware registr v MCU a mohou s ním manipulovat přímo instrukce assembleru, protože se tam strkají i různé data při přerušeních. Správa heapu bývá většinou v kompetenci OS, nebo u MCU ji řeší překladač.
Definicí static řekneš kompiléru, že ta proměnná bude alokována permanentně v dolní cásti paměti. To se hodí třeba u funkcí, kde je třeba znát stav z minulého volání, což přes hodnoty na zásobníku není možné. Globální proměnné jsou všechny static.
Tvůj problém asi bude v nedostatku paměti MCU. S knihovnou nic neuděláš, takže musíš skrouhnout svoje nároky. Použitm makra F v printech, donutíš kompilátor, aby ty textové řetězce uložil do flash paměti, místo do RAM a tak získáš nějakou RAM (výměnnou za výkon). Pokud je práce s řadičem přes I2C pomalá, můžeš vložením delay nechat knihovnu ať zpracuje aktuální data a neprodlužuje dynamické buffery příjmem dalších řetězců, atd...
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail
Valdano



Založen: Jan 01, 2023
Příspěvky: 1692
Bydliště: Česká Lípa

PříspěvekZaslal: ne duben 30 2023, 12:40    Předmět: Citovat

Nejprve vyzkoušejte co zde navrhoval ondraN tj. řetězce ukládat do flešky a ne do RAMky.

Takže například namísto
display.print("Si5351");
použijte
display.print(F("Si5351"));

a stejně tak u dalších volání display.print s různými řetězci textu.

Arduino Pro mini, které zmiňujete má 2kB RAM (tj. pouze 2048 bajtů), a to není mnoho.

Vývojové prostředí Arduino IDE vypisuje využití rozsahu globálních alokací paměti při překladu projektu.

Pokud je to blízko hranice těch 2048 bajtů pak máte v projektu příliš globálních alokací, které bývají v části na počátku zdrojáku, kde bývají deklarovány různé proměnné, pole atd. a z části to může být ukryto i v knihovnách zejména pokud se používají různé objekty jako třeba pro řízení displeje apod.

S knihovnami asi nim moc nenaděláte jak zmínil ondraN leda, že byste použil třeba pro řízení toho displeje nějakou jinou variantu knihovny, která by byla méně náročná na paměť (pokud pro daný účel existuje).

Pokud máte v programu deklarovány nějaké globální pole, které byste mohl zkrátit tak je udělejte pokud možno kratší.

Jakou spotřebu paměti vám při překladu toho projektu vypisuje překladač?

Příklad výpisu viz tento odkaz a různé možnosti optimalizace využití paměti viz tento odkaz.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Celeron



Založen: Apr 02, 2011
Příspěvky: 17725
Bydliště: Nový Bydžov

PříspěvekZaslal: ne duben 30 2023, 14:46    Předmět: Citovat

Valdano napsal(a):

Jakou spotřebu paměti vám při překladu toho projektu vypisuje překladač?


Píšu to hned v úvodním příspěvku, proměnný mají 1300 byte volných. Pole nejsou použitý, stringy taky ne. Právě proto je mi divný, co by mělo zapatlat RAMku. Navíc tyhle výpisy jsou hned na začátku programu ve Void setup(). Přerušení pro n-codér se spouští až po tomhle výpisu. Tady je začátek toho mýho projektu:
kód:

//******************************
#include <Wire.h>               
#include <Rotary.h>             
#include <si5351.h>               
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h> 
#include <EEPROM.h>
//----------------------------------------------------
#define IF  0                            //IF frekvence, např.: 455 = 455 kHz
                                              // + přidá a - odečte IF offset.
#define FREQ_INIT  10000000  //počáteční frekvence při spuštění
#define XT_CAL_F   145350     //Kalibrační faktor Si5351
#define tunestep   A0              //pin použitý tlačítkem kodéru.
#define disPin        A1             //pin na zhasínání displeje
//---------------------------------------------------------------------
Rotary r = Rotary(2, 3);
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire, -1);

Si5351 si5351;

unsigned long freq;                         // 4
unsigned long freqold, fstep;           //  4 + 4
long interfreq = IF;                         //  4
long cal = XT_CAL_F;                     //  4
byte encoder = 1;                          //  1
byte stp, n = 1;                             //   1 + 1
byte value;                                    //   1
unsigned long lastActivityTime = 0;  //  4
int stpAdr = 10;                            //  2
int freqAdr =  20;                          //  2
//------------------------------------------------
void setup() {
  Wire.begin();
  display.begin(0x3C,true);                      // nastavení OLED displeje
  display.clearDisplay();                           // vymazání displeje
  display.setTextColor(SH110X_WHITE);  // nastav bílou
  display.display();                                 // vypiš

  pinMode(2, INPUT_PULLUP);                     // nastavení vstupních pinů
  pinMode(3, INPUT_PULLUP);
  pinMode(tunestep, INPUT_PULLUP);
  pinMode(disPin, INPUT_PULLUP);

  statup_text();                          // v něm se to hryže
 
 


Takže globální proměnný zabírají nějakých 32 byte. Určitě to bude víc, ale víc jich jinde definováno opravdu není.
Zkusil jsem přestěhovat texty v startup_text do flešky a je to naprosto stejný. Jakmile je poslaných víc znaků na displej, hryzne se to. Pokud před texty dám string, tak se to zase chová stejně. Stačí ubrat stejnej počet znaků a maká, pár jich přidám a zase se žvejkne.
Podle mě je problém v knihovně.

_________________
Jirka

Proč mi nemůže všechno chodit hned ?!!
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Mahoney



Založen: Oct 26, 2019
Příspěvky: 381

PříspěvekZaslal: ne duben 30 2023, 15:24    Předmět: Citovat

Asi přetečení proměnný, a chyba v knihovně být klidně může.

Jinak je pěkný že se ti to hryže ve volání
kód:
statup_text();
, ale kde se máme dočíst, co tam je? (a nemá to být "startup_text();" ?)
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Celeron



Založen: Apr 02, 2011
Příspěvky: 17725
Bydliště: Nový Bydžov

PříspěvekZaslal: ne duben 30 2023, 16:26    Předmět: Citovat

Mahoney napsal(a):

Jinak je pěkný že se ti to hryže ve volání
kód:
statup_text();
, ale kde se máme dočíst, co tam je? (a nemá to být "startup_text();" ?)


Je vypsán jako code v prvním příspěvku.

_________________
Jirka

Proč mi nemůže všechno chodit hned ?!!
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Valdano



Založen: Jan 01, 2023
Příspěvky: 1692
Bydliště: Česká Lípa

PříspěvekZaslal: ne duben 30 2023, 17:08    Předmět: Citovat

Chyba může být v knihovně Adafruit SH110X. Když to někam hrábne tak to pak může a nemusí padat v závislosti na tom co a kde to při tom hrábnutí přepsalo. Někdy se může chyba zdánlivě ukrýt tím, že se změní zdroják a po překladu se to v paměti trochu jinak uspořádá a chyba se přestane projevovat což neznamená, že by tam nebyla dál, ale hrabe někam do místa kde to prostě shodou okolností nevadí a tak se to neprojevuje. Takové chyby se velmi špatně hledají. Seznam různých verzí zmíněné knihovny v čase je viz tento odkaz. Pokud máte starší verzi té knihovny tak zkuste použít tu nejnovější verzi 2.1.8. Jestli to bude dělat i s ní.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Mahoney



Založen: Oct 26, 2019
Příspěvky: 381

PříspěvekZaslal: ne duben 30 2023, 17:37    Předmět: Citovat

Celeron napsal(a):
Je vypsán jako code v prvním příspěvku.

Aha tak to se omlouvám. Já to sice četl, ale přehlédl jsem že to je zrovna ono.

Jinak mám ty Adafruit knihovny otevřené ve vedlejších tabech, byl jsem odhodlán že se na to mrknu, ale Valdano má pravdu, jakou verzi té knihovny jsi použil? Resp můžeš zkust novější a dát vědět… (a ještě můžeš zkusit proházet mezi sebou ty include na začátku programu, i když by to teoreticky mělo být jedno, někdy to může zabrat… pokud by to přestalo, pořád by to odpovídalo tomu co napsal Valdano - "chyba sice je, ale hrábne někam kde to nevadí", a pořád se bude blbě hledat Smile )
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Celeron



Založen: Apr 02, 2011
Příspěvky: 17725
Bydliště: Nový Bydžov

PříspěvekZaslal: ne duben 30 2023, 18:11    Předmět: Citovat

Koukal jsem do manažéru knihoven a mám poslední 2.1.18. GFX, která s displejem taky souvisí mám poslední, 1.11.5. Takže buď zkusit starší nebo nevím...
Ale je to zajímavější. Vyměnil jsem ten 1,3" OLED za 0,96" s SSD1306. Má to knihovnu SSD1306 a stejnou GFX. No a co by jste řekli? Je to stejný!!! Tak buď je bordel v GFX a nebo je v těch knihovnách stejná chyba. Mají stejný příkazy, nejspíš stejnej autor a obojí Adafruit.
Ještě to zkusím přepsat na U8GLIB ale to je na delší dobu, jinak se s ní pracuje.
Když to bude neřešitelný, tak se na ten úvodní výpis prostě vykašlu. S další částí zobrazení v obsluze VF generu Si5351 žádnej problém není. A to tam je i grafika, několik velikostí fontu a pod. Ale je to opravdu divný, taková celkem jednoduchá věc jako blbej výpis na displej jedním typem fontu.
Ještě mě napadlo vyházet z obsluhy toho SI5351 některý části, co nejsou vyloženě prioritně potřeba , třeba ukládání do EEprom, zobrazování grafiky, dát kmitočtovej krok natvrdo a zkrátit tak o pár KB program. Jestli se něco změní na těch výpisech.

_________________
Jirka

Proč mi nemůže všechno chodit hned ?!!
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Valdano



Založen: Jan 01, 2023
Příspěvky: 1692
Bydliště: Česká Lípa

PříspěvekZaslal: ne duben 30 2023, 18:42    Předmět: Citovat

Celeron napsal(a):
Píšu to hned v úvodním příspěvku, proměnný mají 1300 byte volných.

Problém je v tom, že překladač vám vypíše jen spotřebu paměti globálních pevně deklarovaných proměnných, ale pokud knihovna alokuje paměť z haldy dynamicky tak to se samozřejmě děje až za běhu programu a tuto spotřebu vám překladač při překladu nezobrazí.

Díval jsem se do základní knihovny Adafruit_GFX, a ta si alokuje pro celou kreslící plochu paměťový bafr (tj. pole) dynamicky funkcí malloc v konstruktoru tj. ještě před voláním těch funkcí pro výpisy textu
kód:
velikost v bajtech = ((sirka + 7) / 8) * vyska;

Takže pokud máte pro ten displej deklarovánu šířku 128 a výšku 64 pixelů, tak se funkcí malloc alokuje dynamicky datový bafr o velikosti
kód:
1024 = ((128 + 7) / 8) * 64;

Když odečteme ten překladačem oznámený zbytek 1300 - 1024 tak najednou zbývá už jen 276 bajtů, a pokud jsou tam ještě nějaké další dynamické alokace třeba v knihovně Wire tak může paměť na haldě lehce dojít a pak se nelze divit tomu, že se někam hrábne a program jak se říká "lehne" a nebo se začne chovat nevyspytatelně. Wink

Pro tyto knihovny by to zkrátka asi chtělo verzi Arduina, která má k dispozici víc paměti RAM tj. zvážit použit namísto Arduino Pro Mini, které má jen 2kB RAM třeba nové Arduino Nano Every, které má 6kB RAM a navíc ještě výkonnější procesor. Pokud máte doma Arduino Mega 2560 tak to zkuste s ním jen na vyzkoušení. Pokud je ten problém způsoben tím, že díky dynamickým alokacím dochází paměť haldy při velikost RAM jen 2kB tak při velikosti 8kB, které má verze Mega 2560 by se ty problémy neměly projevovat vůbec.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
Přidat nové téma   Zaslat odpověď       Obsah fóra Diskuzní fórum Elektro Bastlírny -> Miniaturní počítače (Arduino, Raspberry a další) Časy uváděny v GMT + 1 hodina
Jdi na stránku 1, 2, 3  Další
Strana 1 z 3

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra.
Nemůžete odpovídat na témata v tomto fóru.
Nemůžete upravovat své příspěvky v tomto fóru.
Nemůžete mazat své příspěvky v tomto fóru.
Nemůžete hlasovat v tomto fóru.
Nemůžete připojovat soubory k příspěvkům
Můžete stahovat a prohlížet přiložené soubory

Powered by phpBB © 2001, 2005 phpBB Group
Forums ©
Nuke - Elektro Bastlirna

Informace na portálu Elektro bastlírny jsou prezentovány za účelem vzdělání čtenářů a rozšíření zájmu o elektroniku. Autoři článků na serveru neberou žádnou zodpovědnost za škody vzniklé těmito zapojeními. Rovněž neberou žádnou odpovědnost za případnou újmu na zdraví vzniklou úrazem elektrickým proudem. Autoři a správci těchto stránek nepřejímají záruku za správnost zveřejněných materiálů. Předkládané informace a zapojení jsou zveřejněny bez ohledu na případné patenty třetích osob. Nároky na odškodnění na základě změn, chyb nebo vynechání jsou zásadně vyloučeny. Všechny registrované nebo jiné obchodní známky zde použité jsou majetkem jejich vlastníků. Uvedením nejsou zpochybněna z toho vyplývající vlastnická práva. Použití konstrukcí v rozporu se zákonem je přísně zakázáno. Vzhledem k tomu, že původ předkládaných materiálů nelze žádným způsobem dohledat, nelze je použít pro komerční účely! Tento nekomerční server nemá z uvedených zapojení či konstrukcí žádný zisk. Nezodpovídáme za pravost předkládaných materiálů třetími osobami a jejich původ. V případě, že zjistíte porušení autorského práva či jiné nesrovnalosti, kontaktujte administrátory na diskuzním fóru EB.


PHP-Nuke Copyright © 2005 by Francisco Burzi. This is free software, and you may redistribute it under the GPL. PHP-Nuke comes with absolutely no warranty, for details, see the license.
Čas potřebný ke zpracování stránky 0.27 sekund