# ATMEL mikrokontrolleri >  Konsultāciju vajag par ArduinoMega softu

## Obsis

Jautājums ir sekojošs. Kādai dižiekārtai tika izmesti kādi 2 m3 ar 80~o gadu elektroniku un tā vietā tika ielikts Arduino Mega, kam visi ADC un PWM katrs kaut ko dara, un arī Digi i/o lielākā daļa katrs ir nodarbināts un viss strādā ka prieks.
Bet ir viena ārkārtīgi svarīga funkcija, ko man neizdevās pienācīgi Arduinizēt. 
Kāja Nr48 spēj mērīt laika intervālus ar dubultu precizitāti (16 biti=65636 gradācijas), bet man jāindicē cik Herci ir aizdreifējis kvarca biezummēra sensors no saviem standarta 8 MHz. Tātad uzdevums ir izmērīt 8 MHz ar 1 Hz precizitāti un tas ir biku vairāk nekā 16 biti.
Taisīt interferences sitienus ar otru ģeneratoru lai mērītu tikai diferenci nedrīkst, jo tas kvarcs sāk ar 8 bet beidz savu dzīvi ar 5 MHz, vnk darba laikā tas tiek vakuumapputināts, kļūst biezāks un tāpēc lēnāks. Sekošana ar roku nulles koriģēšanas nolūkos būtu pašnāvniecisks gājiens. Jāmēra frekvence vai laiks.

Tātad ideja darbam ir sekojoša. Arduino skaita savus takts impulsus un lietojam funkciju PulseIn(48,Up,64), kur 48 ir dubultās izšķirtspējas kājas numurs, Up ir palaišanās pēc augošās frontes, un 64 ir maksimālais impulsu skaits mērāmajā paketē - tas darba gaitā tiks variēts/optimizēts. Uz 48.kāju padots 8 MHz izdalīts ar atbilstošu dalītāju līdz 800 Hz. 
Bet, lai iegūtu pietiekamu izšķirtspēju, ir jāpanāk 1), ka iekšējais Arduino CLK dalītājs stāv pozīcijā  Nedalīt (tātad ne Milis, ne Micros, bet gan 62,5 nanosekundes CLK. Instrukcijā gan ir pateikts kods, bet nav pateikts KUR to ierakstīt, jo PulseIn komandai ir tikai trīs parametri nevis četri. 
Otrkārt, ir nepieciešams modificēt skaitīšanas algoritmu, un tas ir visklapatīgāk. Cik saprotu, tad mans 1,25 milisekunžu=800 Hz impulss ir vārti, un skaitāmie impulsi ir Arduino CLK. Un rezultātu šis raksta kādā nebūt RAM šūnā, vienkārši pieskaitot vieninieku, tikko kā uzrodas kārtējā CLK fronte. Cik skatījos PulseIn izdruku, tur ir operatorrindiņa, kas neļauj reģistram pārpildīties, un saceļ trauksmi, ja tas notiek. Bet man kā reiz vajag, lai pārpildās. Man vajag 19 reizes pēc kārtas šo reģistru pārpildīt, jo imho pēc koda 1111 nākošais seko 0000. Tātad process nekur nepazūd un skaitās tālāk, bet 20~ajā reizē paliekošais mērskaitlis ir taisni tas, kurš man ir vajadzīgs, kas satur info par Herciem. Savukārt pazaudētā daļa nes info par Megaherciem, kura nevienu neintersē, tāpat iz zināms, ka 8 vai vienalga cik. Mērķis ir indicēt dažus desmitus līdz simtus Hz nelielu novirzi un izslēgt citai digi i/o pievienoto jaudas atslēgu, kas pārtrauc putināšanas procesu.
Ja kāds varētu palīdzēt ar sakarīgu šīs PulseIn funkcijas pārprogrammēšanu aprakstītajā vai citā tikpat efektīvā veidā, tad es no savas puses varētu piesolīt saprātīgu privātai kabatai paceļamu materiālu atbalstu.

----------


## Obsis

Pārmeklēju ebay piedāvājumus, lētākais 6 zīmju frekvnčmērs ir 91 USD plus muita, taču pirmkārt tas nav 7 zīmju, otrkārt, tam nav skaidra interfeisa uz mašīnu, tātad nāktos to smagi pārtaisīt. Tātad tomēr Arduino ir noteikti pareizākais ceļš. Gan varbūt otrs - Arduino Nano, kas paralēls lielajam Mega. Tas palīdzētu novērst eventuālās problēmas ar nepārtrauktas skaitīšanas izraisītu procesora mazspēju. Es nezinu vai diži daudz procesu tas Atmega2560 spēj vienlaicīgi panest. Ka tik nav viens vienīgs?

----------


## karloslv

Es varbūt nesapratu, jo baigi gari stāsti, bet - ja vajag nomērīt 8MHz signālu ar lielu izšķirtspēju, vienkārši uzliec uz taimera overflow, kurš notiek reizi 65536 tikšķos, vēl vienu skaitītāju - softā palielini vērtību par 1. Vēl vienu taimeri pieslēdz pie references pulksteņa, lai 1x sekundē izsaucas, piemēram, un tas būs tavs gate. Kad gate taimeris nostrādā, nolasi TCNTRx un savu softisko skaitli (pietiek ar baitu, kurš dos 256x65536 = 16M). Man tagad nav pie rokas konkrēta koda piemēra, bet tas ir ārkārtīgi vienkāršs. Aptuvenais kods:



```
volatile uint8_t parpludes = 0;
volatile uint32_t frekvence;

ISR taimera_overflow_interrupts()
{
    parpludes ++;
}

ISR taimera_gate_interrupts()
{
   frekvence = TCNTR1 | ((uint32_t)parpludes << 16);
   parpludes = 0;
   TCNTR1 = 0;
}
```

----------


## M_J

Līdz procesora mazspējai tur vēl vajadzētu būt stipri tālu, ja vien nav ar citām funkcijām aizsisti visi "input capture" moduļi. Nekādus īpašus procesora resursus šis process neprasa, jo taimeri un skaitītāji mierīgi strādā savā nodabā bez procesora iejaukšanās un procesoram tik vien tā darba, kā nolasīt "input capture" reģistros ierakstīto svarīgā notikuma pienākšanas momentu un uzturēt skaitītāja vecākās kārtas, kas jāveido programmiski, jo aparātiski ir tikai 2 baiti. Asemblerī šo funkciju uzprogrammēt nebūtu īpaši sarežģīti, bet šo kodu vajadzētu sakabināt kopā ar C, bet C tā arī dažādu iemeslu tajā skaitā motivācijas trūkuma dēļ neesmu apguvis.

----------


## Obsis

Paldies par idejām, biju jau nospriedis nemocīt rumpi-pumpi bet paņemt lielāku āmuru, konkrēti to STM 32 bitu proci, ko šobrīd virpinu pirkstos. Tiesa tam 0,2 mm lodēšanas laukumiņi vien jau ir tehnisks izaicinājums. Un arī kvarcēts ģenerators uz 80 MHz ir kaut kas jauns manā saprašānā par jebkāda kvarca tehniskajām iespējām, ar koeficientu turpat vai 3. Nu ja vien ņemt 14 MHz kvarca 5 harmoniku, bet kāda garantija, ka tas jau nav 3 harmonikas kvarcs, kaut kā nav dzirdēts, ka 15.harmonika vēl būtu strādātspējīga.

Ja visu varētu nodarīt uz esošā Arduīņa, tas protams būtiski ietaupītu gan darbu gan laiku. 

Ir man viens Assemleri zinošs, kam paprasīt palīdzību. Cik imho saprotu, Arduino labāk saprot Asambleri nekā C++ un vēl švakāk C-Sharp, kaut arī spēj izpildīt jebkuru no minētā un pat Visual Basic arīdzan - jautājums ir vien par noslodzi, un Asamblerim tā ir minimāla. Tātad runa ir par komandrindu optimizācijas kontekstu.

Paldies par teikumu, ka pārslodze nedraud - biju iedomājies, ka Arduino neuztur paralēlus procesus, tātad katrā taktī izpildāmā komanda "plus 1 pie RAM" aizņem 100% mašīnlaika. Labi gan ka tā nav. Aparātiski TIKAI 2 baiti??? Uh! Nu ka tā, tad tā, laikam tomēr manas abas visbiežāk šķirstītās burvju grāmatiņas Arduino Cookbook un Arduino Internals šo faktu nepamatoti noklusējušas. OK.

----------


## JDat

Nav tik traki. Ardūīnim pietiek ar arduīņa IDE un C (vai C++) Esu skatījies rezultāta ASMu. Nav mirstamā kaite.

----------


## zzz

Obsi, stmiem ir leeti discovery kiti. Tur buus gan jau taas siikaas kaajas pielodeetas, gan pareizs kvarcs uzlikts. Un viss izvests uz aaru. 

Tjipa shaadi:

http://lv.farnell.com/stmicroelectro...ery/dp/2215108


O, kaa reizi svezhachoks pienaacis farnelii

http://lv.farnell.com/stmicroelectro...ard/dp/2355377

Cita lieta ka stmam programmeeshana smagaaka kaa arduiinai. Vienkaarshi vairaak fiichu kas jaaizkozh un sarezhgjiitaaka arhitektuura ka atmelim.

----------


## M_J

Par tiem paralēlajiem procesiem varbūt ne tā izteicos. AVR (nelietošu vārdu Arduino, jo strādāju ar AVR kontrolleriem bet ne ar Arduino) centrālais ALU tik tiešām katrā taktī (vai katrās vairākās taktīs, ja ir sarežģītāka komanda) izpilda tikai vienu komandu un palielina komandu skaitītāju. Nekādas vairākas darbības vienlaicīgi tas darīt nespēj. Bet AVR nesastāv tikai no ALU un atmiņām. Tur ir virkne taimeru, ADC, UART utt. un katra no šīm sastāvdaļām ir lielā mērā spējīga funkcionēt autonomi un vai nu caur statusa bitiem attiecīgajos reģistros, vai caur pārtraukumiem darīt zināmu ALU, ka ir piefiksēts kādas frontes kādā ieejā laika moments, notikusi skaitītāja pārpildīšanās, nosūtīts vai uztverts baits, vaikts ADC pārveidojums utt. Tas ļauj netērēt ALU resursus teiksim katra impulsa piefiksēšanai, bet paziņo tam, kad darbs ir padarīts un ALU var attiecīgajos reģistros saņemt jau gatavu rezultātu. Konkrētajās situācijas risināšanai es izmantotu "input capture" moduli. Tas ir modulis, kurš "input captpture" reģistrā piefisksē aparātiskā taimera stāvokli (2 baiti) momentā, kad "input capture" ieejā pienāk iepriekš definēta fronte. Tas, ka ALU tajā brīdī nodarbojas ar kaut ko citu un momentā nevar reaģēt nav nekas traģisks. Frontes pienākšanas precīzu laika momentu ir piefiksējis "input capture" modulis un tur tas glabāsies, kamēr ALU labpatiksies viņu nolasīt. Drusku sarežģītāk ir ar taimera vecākajiem baitiem, kas jāorganizē programmiski. Tur jāuzmanās laika momentos, kas tuvi aparātiskā taimera pārpildīšanās momentam. Vajag izveidot mehānismu, kas izslēdz situāciju, kad aparātiskais taimeris ir jau pārpildījies, bet taimera programmiski organizētā vecākā kārta vēl nav paspēta tikt palielināta un šajā brīdī ALU nolasa rezultātu no taimera aparātiskās daļas, kas ir pareiza un arī no programmiski organizētās daļas, kas nav pareiza. (esmu uz šādas problēmas uzrāvies)

----------


## Obsis

RE: zzz
Wow, paldies. Tas ir incanti: zināšanai
Kaut arī konkrētajā gadījumā ērtāk ir saprogrammēt to verķi kas already ir uzstādīts un apkalpo sistēmu, pat pareizā kāja jau pielodēta. Un nevis taisīt ko jaunu un lipināt paralēli esošajam.

RE:M_J
Paldies, tā ir laba ziņa. Taču laimīgā kārtā man vecākie biti ir pie kājas. Tie ne mūžām nevar mainīties, tāpēc tos droši drīkst pazaudēt.

----------

