AVR arduino potize

Martin Locker locker na vosrk.cz
Úterý Duben 13 20:16:41 CEST 2021


To je celkem jasné. Funkce millis() v arduinu není napsaná zrovna ideálně.
Nepočítá milisekundy, protože používá dělení 8-mi bitovým čítačem až do přetečení.
Tudíž výsledná frekvence není 1kHz, ale 16MHz/64/256. Tudíž po jisté době tam dochází ke korekci, která se projeví tím "výpadkem".
Takže nepoužívat pro časování funkci millis, ale udělat si časování svoje. Buď navrhované zavěšení na Timer1 (pokud nepotřebuju serva), Timer2, nebo si Timer0 přeprogramovat, aby čítal jen do 250. Prostě napíšu obsluhu přerušení a nastavím čítač do vhodného módu. 

To vypadávání znaků na seriáku je divné (to se mi nikdy nestalo).

Jinak na hraní je Arduino prima (když potřebuju něco rychle vyzkoušet), ale jinak je rozumnější si to napsat sám, než zkoumat neduhy všech možných knihoven.

S přáním pevného zdraví
Martin Locker

----- Původní zpráva -----
Odesilatel: Jaroslav Buchta (jaroslav.buchta na hascomp.cz)
Datum: 13/04/2021 20:06
Příjemce: HW-news (hw-list na list.hw.cz)
Předmět: AVR arduino potize

Snazim se pomoct se zpracovanim signalu, vzorkovani po 1ms a zda se, ze
neco se v knihovnach seka (tipuju obsluhu serv) a za 100ms mi to vynecha
tak 2-3 cykly, za sekundu asi 25 takže je to asi celkem rovnoměrné.

Dá se nějak pověsit na ISR 1ms od timeru 0? Podle zdrojaku to na nejakou
možnost callback fce nevypada (timer1 je použit pro serva)

Neřešim zatim teda, jestli to nevynechava i ta přerušeni. Jako
doporučuju synovi hodit ten AVR drek po psovi ale zatim rychlou nahradu
nemame ;-)

Zkousel jsem Nucleo303RE, to funguje i jako arduino hezky ale je to
velke. Neco velikosti Arduino Nano s normalnim 32b procesorem neni?
(nasel uz nejakou exotiku CM4 ale maji to jen na mouseru a moc se mi to
nelibi, odkaz ted nemam)

Jo, a jeste to vynechava znaky vysilane na serial, zcela nahodne, nekdy
to jede pul minuty bez vypadku, nekdy vypadne znak po par sekundach,
nejaky znamy problem? Terminalem to neni, zkousel jsem ruzne ktere mi
normalne fungujou na 115200

Ono to teda nejak funguje jak jsem to zkorigoval, ale se.e me to...

V loop se volaji v redukovane verzi jen tyto metody

#define MSGPERIOD   1000
void CDataProc::Message()
{
    uint32_t ms = millis();
    if (ms - msgMillis < MSGPERIOD)
    {
        return;
    }
    msgMillis += MSGPERIOD;
    char s[40];
    sprintf (s, "%10lu, %4u, %5u, %5u", msgMillis, cycles,
(uint16_t)(valSignalFilt >> 8), (uint16_t)(valAvgFilt >> 24));
    Serial.println(s);
    cycles=0;
}

uint16_t CDataProc::GetSignal()
{
    uint16_t sensorValue = (uint16_t)analogRead(A0);

    if (firstPass){
        valAvgFilt = ((uint64_t)sensorValue << 24) | 0x7fffffUL;
        valSignalFilt = ((uint32_t)sensorValue << 8) | 0x7f;
        firstPass = false;
    }
    else
    {
        uint32_t ms = millis();
        if (ms - lastMillis > 0)
        {
            cycles++;
        }
        while (ms - lastMillis > 0)
        {
            lastMillis++;
            valAvgFilt = (valAvgFilt*(coefAvg-1) +
(((uint64_t)sensorValue << 24) | 0x7fffffUL))/coefAvg;
            valSignalFilt = (valSignalFilt*(coefSignal-1) +
(((uint32_t)sensorValue << 8) | 0x7f))/coefSignal;
        }
    }
    Message();
    return (int16_t(valSignalFilt >> 8)) - (int16_t(valAvgFilt >> 24));
}

Vypis vypada takto napr.

     53000,  976,   741,   741
     54000,  977,   741,   741
     55000,  976,   741,   74            //vypadek
     56000,  977,   741,   741
     57000,  977,   741,   741


    188000,  976,   741,   741
    189000,  977,   741,   741
    190000,  976,   741,   741
    191000,  977,   41,   741        //vypadek
    192000,  976,   741,   741
    193000,  977,   741,   741
    194000,  977,   741,   741
    15000,  976,   741,   741        //vypadek
    196000,  977,   741,   741
    197000,  976,   741,   741

_______________________________________________
HW-list mailing list  -  sponsored by www.HW.cz
Hw-list na list.hw.cz
http://list.hw.cz/mailman/listinfo/hw-list



Další informace o konferenci Hw-list