Mám tady vzorek vývojový desky Silabs C8051F392. 16 bitů časovač by se plnil kmitočtem 25MHz, což by dalo při měření až 2,65ms, z obsahu spočítat reverz, v druhým časovači odečítat dýlku výstupního signálu. V asembleru je u F392 většina instrukcí jenocyklových na kmitočtu 50MHz. Šváb je o trochu větší než ATtiny a kolem nepotřebuje vůbec žádný součástky. Výzva si zopáknout A51, s kterým jsem dělal už před 30 lety.
Servoreverz s ATtiny85
Moderátor: Moderátoři
Mám tady vzorek vývojový desky Silabs C8051F392. 16 bitů časovač by se plnil kmitočtem 25MHz, což by dalo při měření až 2,65ms, z obsahu spočítat reverz, v druhým časovači odečítat dýlku výstupního signálu. V asembleru je u F392 většina instrukcí jenocyklových na kmitočtu 50MHz. Šváb je o trochu větší než ATtiny a kolem nepotřebuje vůbec žádný součástky. Výzva si zopáknout A51, s kterým jsem dělal už před 30 lety.
Proč mi nemůže všechno chodit hned ?!!
Ch32v003 stoji centy a maclkom potencial. https://pallavaggarwal.in/2023/09/23/ch ... utput/amp/
- Dumitru
- Příspěvky: 254
- Registrován: 11 pro 2015, 00:00
- Bydliště: Slovensko,Bratislava
- Kontaktovat uživatele:
Celeron píše:A jak chceš časovačem, kterej se plní periodou 1us něco přesně u takovýhleho signálu měřit?
Možno blba otázka ale mne nie je jasne prečo 1us(1Mhz) ? ak máš 8Mhz čo je 125ns, 125*256(8bit)=32000ns alebo 32us , počas 1us vieš napočítať do 8
Vidím že tam máš prerušenie treba tam v SW počítať s týmto , vbehnúť do prerušenia trvá dlhšie ako z neho vyjsť von
Kód: Vybrat vše
3.8.1 Interrupt Response Time
The interrupt execution response for all the enabled AVR® interrupts is four clock cycles minimum. After four clock cycles the
program vector address for the actual interrupt handling routine is executed. During this four clock cycle period, the program
counter is pushed onto the stack. The vector is normally a jump to the interrupt routine, and this jump takes three clock
cycles. If an interrupt occurs during execution of a multi-cycle instruction, this instruction is completed before the interrupt is
served. If an interrupt occurs when the MCU is in sleep mode, the interrupt execution response time is increased by four
clock cycles. This increase comes in addition to the start-up time from the selected sleep mode.
A return from an interrupt handling routine takes four clock cycles. During these four clock cycles, the program counter (two
bytes) is popped back from the stack, the stack pointer is incremented by two, and the I-bit in SREG is set.
Píšeš že tam maš 8Mhz kryštál predpokladám že externý a nefunguješ od interných hodín inak je to potrebne kalibrovať , mne bez kalibrácie ani UART na 9600baud nefungoval .
No a nakoniec z datasheetu prvá strana Attiny môže ísť až do 20Mhz.
Dumitru píše:Možno blba otázka ale mne nie je jasne prečo 1us(1Mhz) ? ak máš 8Mhz čo je 125ns, 125*256(8bit)=32000ns alebo 32us , počas 1us vieš napočítať do 8
Ano, můžeš nastavit TCCRB na xxxxx001, tedy vstup přímo CLKi/o (No prescaling) od hodin 8MHz ale pak s 8 bitama TC0 napočítáš jen jak píšeš do 32us. Jenže měřený signál může mít až 2,2ms. Tak si spočítej, kolikrát bys musel nechat TC0 vygenerovat přerušení od přetečení TC0 a přičíst 1 v registru, kterej by nahrazoval vyšších 8 bitů pro pseudočasovač 16 bitů. Skoro 70 krát. Jak se časově zpracovává přerušení jsi tu popsal. S jakou přesností by to asi měřilo? Prostě na ATtiny85 s časovačema 8 bitů to nejde s dostatečnou přesností a stabilitou realizovat.
Proč mi nemůže všechno chodit hned ?!!
Proč mi nemůže všechno chodit hned ?!!
Ten procák prostě není na měření kolem 1us dost rychlej a nepřítomnost 16 bit časovače to ještě umocňuje.
Zkusil jsem napsat test časovače aby se na portu změnila hodnota při každým přetečení časovače a k tomu jsem dával prescalery, co Tiny 85 nabízí.
A už tady byl problém, ten signál na PB1 se náhodně chvěl o cca ± 2us. Takže je vidět, že tudy cesta nevede kvůli nepředvídatelnýmu chování časovačů při intervenci. Jestli si někdo myslíte, že víte kde je problém, tak sem s tím, budu docela vděčný.
Kód: Vybrat vše
// Přerušení při přetečení časovače
ISR(TIMER1_OVF_vect) {
// Přepnout stav na výstupním pinu
PORTB ^= (1 << PB1);
}
//-------------------------
void setup() {
// Nastavit PB1 jako výstup
DDRB |= (1 << PB1);
// Inicializace časovače1
TCCR1 = 0; // Zastavit časovač
TCNT1 = 0; // Vynulovat časovač
// Nastavit prescaler na 1,2,4,8,16,32,64,128,256,512,1024...)
TCCR1 |= (1 << CS13); // CS13 na 1 pro prescaler 128
// Povolit přerušení při přetečení časovače
TIMSK |= (1 << TOIE1);
// Globálně povolit přerušení
sei();
}
//-----------------------
void loop() {
}Proč mi nemůže všechno chodit hned ?!!
Kód: Vybrat vše
ISR(TIMER1_OVF_vect) {
PORTB ^= (1 << PB1);
}
void setup() {
DDRB |= (1 << PB1);
// Zapsat do WDTCR registru pro povolení změny
WDTCR |= (1 << WDCE) | (1 << WDE);
// Vypnout WDT
WDTCR = 0x00;
TCCR1 = 0;
TCNT1 = 0;
TCCR1 |= (1 << CS13); // CS13 na 1 pro prescaler 128
TIMSK |= (1 << TOIE1);
sei();
}
void loop() {
}Proč mi nemůže všechno chodit hned ?!!
Kód: Vybrat vše
// Přerušení při přetečení časovače 2
ISR(TIMER2_OVF_vect) {
// Přepnout stav na výstupním pinu
PORTB ^= (1 << PB1);
}
void setup() {
// Deaktivovat watchdog timer
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = 0x00;
// Nastavit PB1 jako výstup (pin 9)
DDRB |= (1 << PB1);
// Inicializace časovače2
TCCR2A = 0; // Normální režim
TCCR2B = 0; // Zastavit časovač
TCNT2 = 0; // Vynulovat časovač
// Nastavit prescaler na 64
TCCR2B |= (1 << CS22); // CS22 na 1 pro prescaler 64
// Povolit přerušení při přetečení časovače
TIMSK2 |= (1 << TOIE2);
// Globálně povolit přerušení
sei();
}
void loop() {
}
Ještě zkusím Tiny85 převýst z interního oscilátoru na krystal. Ale musím s1 k programátoru USBASP udělat destičku s krystalem a kondíkama, protože jak bych jednou přepnul fuse na krystal, tak je procík bez krystalu nedobytnej. V nejhorším mám na Tiny85 HVresetátor, ten si s ním poradí.
Proč mi nemůže všechno chodit hned ?!!
- nostalcomp
- Příspěvky: 169
- Registrován: 09 lis 2022, 00:00
Takže:
Napíšeš, že máš hotovo (bez dalších podrobností) a přidáš fotku hotového reverzu, který údajně necuká. Fotka je pod textem o zapůjčeném továrním výrobku, což je přinejmenším matoucí. Jen o pár dní později už ale tvrdíš, že to s Attiny85 technicky nejde a vymejšlíš blbosti.
Píšeš cosi o verzi v assembleru, ale dáváš sem pořád zdrojáky v Céčku a ani neuvedeš čím to překládáš. Pokud to překládáš v Arduino IDE, tak nezapomeň, že překladač do kódu dodá aktivaci Timeru 0 a jeho obslužnou ISR kvůli funkcím millis a micros. Ty jsou pro servoreverz zbytečné a jen zdržují vykonávání programu. Pokud by se to psalo v opravdovém assembleru, tak si to tam člověk přece zbytečně nedá. A bůhví co ještě se tam automaticky přidává. On ten Arduino překladač vůbec umí "pěkný věci". Doporučuji přečíst třeba toto: Arduino poťouchlost – funkce map(). Proto taky nepoužívám funkci MAP a vždy si přepočty dělám "ručně". Mimochodem, autor toho textu se prý ozval tvůrcům Arduino překladače, upozornil je na chybu a navrhl opravu. Dostal odpověď ve smyslu toho, že se o chybě ví, ale nelze přepisovat definice funkcní kvůli zpětné kompatibilitě. Podobně je třeba dávat bacha na servoknihovnu a taky na řetězce. A kdoví, jaké další chyby a "ďáblové" se v překladech zdrojáků vyskytují.
Zpočátku pořád uvádíš, že timer je taktován impulsy s periodou 1uS a také píšeš, že strojový cyklus při 8MHz trvá 1uS. Ten timer už tu byl vyvrácen. S prescalerem nastaveným na 1 mají vstupní impulsy timeru periodu 125nS. A co se týká jádra CPU, tak i to lze 8x zrychlit nastavením registru CLKPR, resp. shozením pojistky CLKDIV8 (z výroby je nastavena!). Pak bude i strojní takt 125nS. To se pak člověk nediví, když lidi, než aby si prostudovali datasheet, raději rovnou sáhnou po výkonnějším procesoru.
Pokud se to napíše opravdu efektivně a budou se vybírat primárně 1-cyklové instrukce, tak to chodit prostě musí. Já bych se držel toho algoritmu s odečítáním vstupního servopulsu od 3ms. A je jedno, jestli budou servopulsy 1-2mS, nebo 0,8-2,2mS nebo 0,6-2,4mS. Pokud to bude symetrické kolem středu 1,5mS, vždy je stačí odečíst od 3mS. Na celý program pak stačí jedna jediná proměnná typu byte, která bude suplovat horní byte časovače. Žádný wordy nebo dokonce longy. V mezidobí bude vždy nastavena na 0 a v ISR timeru pak inkrementována a v hlavní smyčce testována. Timer bude vždy spouštěn na náběžku servopulsu a bude nastaven na automatický HW autoreload po 240 taktech (30uS). Je úplně jedno, jak dlouho trvá obsluha přerušení (pokud nebude větší než těch 30uS, což asi nehrozí). V okamžiku jeho obsluhy už si timer pojede dál svým životem. Testování náběžky a sestupky servopulsu a testování dočítání 3mS bych dělal v hlavní smyčce. Viz. průběhy v mém předešlém příspěvku. Nějaká chyba tam bude vždy. Ale určitě ne 2uS a bude víceméně konstantní a je tak možno ji korigovat úpravami hodnot reload a prom. Zkoušel jsem si to napsat na papír v jakémsi "esperantoassembleru" x51 a je to na pár bajtů. Do 2KB Attiny25 se to musí vejít 20x. Snažil jsem se vybírat instrukce, které mají AVR ekvivalent. Bohužel nemám žádný vhodný (=jednoduchý, ideálně pro DOS) AVR assembler, jako je TASM. Nevíte o něčem?
Kód: Vybrat vše
;"x51 esperantoassembler"
;jedno z mnoha moznych reseni
Start:
clr servo_out
di
timer stop, CLKcpu = CLKosc/1
nastavení timeru, prescaler /1, autoreload (256-240 = 16)
timer Interrupt enable
init:
prom = #0 ;nastaveni pom. promenne (MOV, LDI apod.)
jnb servo_in, $ ;cekani na nabezku
timer start
jb servo_in, $ ;cekani na sestupku
setb servo_out ;inverzni servopuls start
cyk: ;cekani na dokonceni casovani 3 mS
mov a, prom ;lze resit mnoha zpusoby (AVR stejne nema akumulator)
cjne a, #100, ($+3)
jc cyk ;prom < 100, opakuj
clr servo_out ;inverzni servopuls stop
timer stop
;spousta casu na stourani se v uchu ci nose...
jmp init ;jdeme cekat na dalsi nabezku
ISR_tim: ;obsluha preruseni od timeru (ma autoreload)
inc prom
reti Ještě mě napadlo pro sichr dát na ten servovýstup 1nF keramiku proti GND, jako se to doporučuje u výstupu 555 při vazbě na logické obvody. Ale asi (určitě) je to úplně zbytečné.