# ATMEL mikrokontrolleri >  ATMELis un assemblers

## Jurkins

Nolēmu tomēr rakstīt jaunā tēmā.
Tātad turpinu cīnīties (iepazīties) ar ATTINY13. Uz darbagalda ir watchdog un enerģijas taupības režīmi. Uzrakstīju kodu, kas iestāda watchdog taimeri uz maksimālo periodu, dodu šim tiesības ar pārtraukumu pamodināt čipu un tad cilpā iedzenu čipu power down stāvoklī. Pārtraukumā nenotiek nekādas darbības, tikai čips pamostas un turpina darbības - šajā gadījumā invertē vienu izeju pie kuras ir LEDs, tad atlec uz cilpas sākumu un atkal tiek iedzīts power down stāvoklī. Līdz nākamajam pārtraukumam. Viss strādā. LEDs apmēram 8 sekundes dae, tad 8 sekundes nedeg u.t.t. Bet radās jautājums:
  Tātad izejas power down modē paliek tā kā bija? Nav tā, ka visas tiek atrubītas nost? Jebšu esmu kaut ko saputrojis, un čips netiek iedzīts power down? Datašītā īsti nevaru saprast. Raksta, ka i/o clk tiek apturēts, bet kas notiek ar izejām...


```
.macro outp 
    ldi temp, @1
    out @0, temp
.endmacro

.org 0x0000
    rjmp _reset_
.org 0x0008
    rjmp _iv_wdt_
     
_reset_:
    cli
    outp SPL, LOW(RAMEND)
  
    outp WDTCR, (1<<WDCE)
    outp WDTCR, (1<<WDP0)|(0<<WDP1)|(0<<WDP2)|(1<<WDP3)|(1<<WDTIE)
    outp MCUCR, (0<<SM0)|(1<<SM1)|(1<<SE)
    sei

_main_:
    sleep
    sbic PORTB, PB4
    rjmp lbl_clear_bit
    sbi PORTB, PB4
    rjmp _main_
lbl_clear_bit:
    cbi PORTB, PB4
    rjmp _main_

_iv_wdt_:
    reti
```

----------


## JDat

Nu. Savulaik spēlējos ar tiny2313. Bija bišku citas prasības, bet... Uzmanīgi jīzlasa vaisas nianses par power down lietām. iklīdz kaut ko neievēro tad nekas nestrādā. Jurkinam iss itkā strādā. Atceros ka bija rekomendācija par enerģijas parētiņa samaināšanu un manipulācijam ar PINiem lai samazinātu realo patēriņu. Filosofiski jāpieņem ka katra kāja ir kā MOSFETu pustilts+ESD diodes. Aizsūtot MCU gulēt apstājas clock generatori un CU neko netērē. Pamostoties (WDT vai kas cits) tiek palaisti MCU clock generatori un nospieta (iespējams advancēta, lai netraumētu PINus) reset poga. Ir jālasa datasheet un jaeksperimentē. Piemeram paskaties kādā stāvoklī ir DDR, PORT un PIN pēc pamošanās. Vārdu sakot tur ir nianses kuras atkarīgas no konrētā udevuma un MCU sleep realizācijas.

----------


## Powerons

Kāda velna pēc tu to dari assamblerā!!!!!!!!!!!!!!!!!!????????????
Sarežģītības par maz.

Ja iedzen atmeli gulēšānā tad cik atceros arī izvadi jāizzslēdz, citādi atmelis guļ patērā kaut kādus tu nanoampērus, mikroampērus, vai cik nu tur bija bet taus ledz uz kājas 20MA un nekāda ekonomija. Neatceros kas bija ar iebūvēto puul up.


Es kādreiz taisīju ko samērā līdzīgu uz Tiny45 un Tiny85, mazāki nebija.

Te mana programma vari izķidāt kā piemēru.



```

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <util/delay.h>

//#define F_CPU 1000000UL

#define START_DELAY 15         //Seconds Blink led
#define VALVE_ON_TIME 1000     // mili seconds
#define DELAY_AFTER_MOUTION 15 //Seconds


#define LED_OFF() PORTB&=~(1<<PB1) //2
#define LED_ON()  PORTB|=(1<<PB1)
#define LED_OUTPUT_MODE()   DDRB|=(1<<PB1)

#define VALVE_OFF() PORTB&=~(1<<PB4)
#define VALVE_ON()  PORTB|=(1<<PB4)
#define VALVE_OUTPUT_MODE() DDRB|=(1<<PB4)

#define MOUTION_DETECTOR_INPUT_MODE() DDRB&=~(1<<PB3)


unsigned int cikls;

ISR(WDT_vect) 
{
 WDTCR |= _BV(WDIE); // Alow wachdog interupt, otherwise reset
}


int main(void)
{
   LED_OUTPUT_MODE();
   VALVE_OUTPUT_MODE();
   VALVE_OFF();
   MOUTION_DETECTOR_INPUT_MODE();

   ADCSRA &= ~(1<<ADEN);                     //turn off ADC
   ACSR |= _BV(ACD);                         //disable the analog comparator
   MCUCR |= _BV(7) | _BV(2);                 //turn off the brown-out detector


  for (cikls = 0; cikls < START_DELAY; cikls++)
     {
      _delay_ms(250);
      LED_ON();
      _delay_ms(250);
      LED_OFF();
      _delay_ms(250);
      LED_ON();
      _delay_ms(250);
      LED_OFF();
      }


 while(1)
  {
   VALVE_OFF();
   if(PINB&(1<<PB3)) 
    {
     VALVE_ON();
     _delay_ms(VALVE_ON_TIME);
     VALVE_OFF();
     for (cikls = 0; cikls < DELAY_AFTER_MOUTION; cikls++)     _delay_ms(1000);
    }
  VALVE_OFF();


// Sleep controll                          
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // do a complete power-down
  sleep_enable();                      // enable sleep mode
  sei();                               // allow interrupts to end sleep mode                                    
  wdt_enable(WDTO_60MS);
  WDTCR |= _BV(WDIE);                  // Alow wachdog interupt, otherwise reset
  sleep_cpu();                         // go to sleep
  sleep_disable();                     // disable sleep mode for safety
  wdt_reset();
  wdt_disable();
  cli();                               // disable interupts
   }

}
```

 Manā piemērā Atmelis guļ, ik pa laikam pamostās, apskatās, kas notiek, un ja vis OK tad atkal ātri iet gulēt.

----------


## Jurkins

To vai veikt tikai pamodināšanu un iet uz priekšu vai pamodināt un restartēt var izvēlēties. Manā gadījumā ir pamodināšana bez restarta. PORT un DDR toč ir tādā pašā stāvoklī kā pirms miega. Tam tā arī pēc loģikas vajadzētu būt. Bet mani izbrīna, ka miega laikā tas LEDs turpina degt, ja ir iedegts, MCU kloki izslēdzas un enerģiju netērē, bet, ja kaut kas ir pie porta un ir ieslēgts, tad turpina tērēt enerģiju. Var jau būt, ka tas ir pareizi un loģiski, un par to, lai netērētu ir jāparūpējās pašam.
Uzrakstīju un ieraudzīju Powerona atbildi. Paldies. To arī gribēju dzirdēt, ka par izvadiem jāparūpējas.
Kāpēc assemblerā? Izglītošanās nolūkos. Nu nav jau šis tik sarežģīts! Sevišķi šitādiem maziņiem nolūkiem.

----------


## JenertAndzins

ir doma arī izmēģināt uzkodēt kaut ko 'vienkāršu asamblerī, bet katru reizi, kad ieraugu, paliek bail  ::

----------


## JDat

Atgādināšu. Patēriņs nesamazinās uz 0 femtoampēriem. CMOS trigeri rij enerģiju pārslēgšanās brīdi, tāpēc patēriņš ir miliampēros. Kamēr vis atrodas stabilā stāvoklī (clk nav, nekans netiek pārslēgts), timēr patēriņš ir nanoampēros. Attiecīgi IO reģistri paliek noteiktā stāvoklī un netērē neko, vai tērē gandrīz neko (nA). Paskaties uz iseju jā half-bridge shēmiņu. Tur nav nekā, kas var tērēt, jneskaita CMOS SR trigerus reģistors, bet tie ir nanoampēri. Nejauc absoluto nulli ar skaitli, kurš ir tuvs absolūtai nullei.

----------


## Jurkins

Kā māca vecs latviešu sakāmvārds - acis darba izbijās, rokas darba nebijās  :: . Kamēr nebiju iesācis, tas asms likās kaut kas drausmīgs. Bet tad tā lēni un mierīgi uzkodēju visu (gandrīz, grūtāko uzkodēju) "1 wire" algoritmu. Protams, ka lasīju literatūru un skatījos paraugus.
Protams, vienmēr var teikt - tak paņem atmeli ar 256K programmu atmiņu un kodē kaut C# (pārspīlēju laikam :: ), un teicējam būs taisnība zināmā mērā. A bet es sporta pēc gribu iedzīt to visu 1K  :: .

Poweron, visu saprotu Tavā programmā izņemot vienu:
  kāpēc suņa pārtraukumā vajag atļaut pārtraukumu?

----------


## M_J

Katram savs. Man assembleris tieši liekas vienkāršs. Atliek zināt tos dažus desmitus komandu un visu var iztaisīt, un galvenais - patiešām zini, kā tas viss strādā. Bet kā C ir organizēts, piemēram, delay_ms(250); ? Kā es varu uzzināt, cik tas ir precīzs? Assemblerī es to aiztures precizitāti zinu precīzi. Man kolēģis, kas programmē attiny C pašreiz cīnās ar delay precizitāti. Patreiz taisu uz PC programmu, kas sazinās ar mikrokontrolieri un nodrošinās, lai uz datora ekrāna vizuāli attēlotu to, kā darās Atmelis. Taisu to Javā. Kāpēc tieši Javā? Tāpēc lai strādātu gan zem windows, gan linux un vēl visa kā cita. Vot Java tās gan ir šausmas! Viss tas lērums swing komponentu metožu, kas ir jāzina, lai kaut ko uz ekrāna saveidotu. Starp citu javā tie delay ir kaut kas drausmīgi neprecīzs, Pietiek paralēli uz datora palaist kādu citu procesu un tie delay intervāli sāk stiepties. Delphi7, ar ko darbojos iepriekš - tāpat. Nevaru sagaidīt, kad atkal tikšu no šitā vājprāta atpakaļ pie assemblera.

----------


## ansius

avr asm nav ne vainas, pats savu laiku knibinājos. tagad gan aiz slinkuma, sīkumus uz arduino taisu. Neko nopietnāku pagaidām nav bijis vajadzība lietot. Bet jā power down jau tikai pašā procesorā tupa enerģiju, par pārējo jārūpējas pašam.

----------


## Jurkins

Vispār konkrētie humori ar tiem tīņiem.
Ja sunim ieliek vieninieku WDTIE bitā, tad šis taisa tikai pārtraukumus, ja ieliek vieniniekus gan WDTIE gan WDE, tad pirmajā reizē uztaisa tikai pārtraukumu, otrajā  pārtraukumu un aiziet uz reset. It kā viss ok, tā jābūt. Nomainu WDE atkal uz nulli, nokompilēju, pāršuju,bet tīnis turpina katrā otrajā pārtraukumā iet uz resetu. P....s kā mazais ezītis :: , kamēr pamēģināju ielikt citu tīni. Iešuju to pašu - viss ok, tikai pārtraukumi. Uzlieku WDE = 1, nokompilēju iešuju - viss ok, pārtraukums, tad pārtraukums + resets. Nomainu atpakaļ WDE = 0, nokompilēju, iešuju. Bāc! Atkal vecā dziesma. Atlieku atpakaļ iepriekšējo tīni (kuram palika WDE = 0, bet negāja kā vajag), viss ok. Izrādās, viss ok, ja noņem uz brīdi barošanu. WTF? ::

----------


## JDat

Varbūt FUSES?

----------


## Jurkins

FUSES vispār neaiztieku. Watchdog always on nav iešūts.

Joks jau tāds, ka noņemot un pieliekot barošanu viss aiziet kā vajag.

Nē, nu ok, viss jau it kā ir labi, bet ar citiemm instrumentiem -  taimeriem, komparatoriem, ADC nekas šitāds nav bijis.

----------


## JDat

39. lpp zem koda un 40. lpp pirms koda. Izlasi uzmanīgi!

----------


## Jurkins

Oh, velnos. Šito palaidu garām. Sanāk, ka vnk pāršujot čipu, ja barošana netiek pārtraukta, suns turpina būt modrs ar vecajiem parametriem?


Nja, biju palaidis garām vienu teikumu no 38 lappuses.

1. In the same operation, write a logic one to the Watchdog change enable bit (WDCE)
and WDE. A logic one must be written to WDE regardless of the previous value of the
WDE bit.
2. Within the next four clock cycles, write the WDE and Watchdog prescaler bits (WDP) as
desired, but with the WDCE bit cleared. This must be done in one operation.

Paldies, JDat, par pareizo virzienu!

----------


## JDat

Tagad atceros. Pie katras WDT manipulācijas vispirms jānereseto WDT (vienā grāmatiņa bija komentāts pie koda: brosaem kostocku sobake) un tikai tad javeic manipulācijas. Vajadzības gadījumā vēlreiz jānoreseto WDT.

----------


## Jurkins

Problēma bija pašā manipulācijā. Vispirms bija jānodzēš suņa reseta karogs un tas wde vispirms obligāti 1 un tad tikai 0. Ja noņem barošanu, tad šie nodzisa un tipa viss gāja.

----------


## Jurkins

Netaisīšu jaunu tēmu.
Jautājums par avr asmu.
Kāpēc "subi r16, 100" uzmet iekš SREG negatīvo karogu, ja r16 vērtība ir >227, tas ir rezultāts ir 128 vai lielāks. Vai tur ir kaut kāds sakars ar to, ka asms vienmēr domā, ka notiek darbošanās ar signed vērtībām?

----------


## M_J

Ja darbības rezultātā vecākais bits ir uzmests, tiek uzmests negatīvais karogs. Strādājot ar bezzīmes skaitļiem es pie salīdzināšanām un atņemšanām skatos C karogu.

----------


## Jurkins

Paldies, sapratu domu. Tagad viss notiekas kā vajag. 
p.s. darbībās arnegatīvajiem skaitļiemvēl tā īsti neesmu iebraucis.

----------


## M_J

Es arī ne. It sevišķi ja skaitļi ir vairāku baitu. Ja sanāk darīšana ar negatīvām vērtībām, pārtaisu pozitīvas, izdaru kas darāms, un beigās atkal pārtaisu negatīvu. Tā lielākā ņemšanās iznāk, ja vajag dalīt divus vairāku baitu lielumus vienu ar otru. Kur vien varu, cenšos aprēķinus izkombinēt tā, lai dalīšanu varētu aizstāt ar reizināšanu, jo lielākajaii daļai AVR aparātiskais reizinātājs ir, bet dalītājs nav nevienam. Bet izdalīt teiksim vienus 3 baitus ar otriem 2 baitiem tomēr aizņem simtiem ciklu.

----------


## next

Offt.
A man bija gadiijums kad reizinaashanu aizstaaju ar 2 daliishanaam.
Jo daliishanas proceduura tur bija jau no saakuma a reizinaashanu vajadzeeja klaat pierikteet. ::

----------


## Jurkins

Es konkrēti vakar rakstīju binārā skaitļa pārvēršanu trīs ciparos komats vēl viens cipars. Tā kā DS1820 Tmax ir 125, tad aprakstītā problēma it kā netraucē, bet nejauši ieliku lielāku skaitli un ... bļin. It kā jau sapratu, kur suns ir aprakts, bet vienkāršu skaidrojumu vienā teikumā, kā uzrakstīja M_J, neatradu. Dalīšana un reizināšana man vēl priekšā  :: .

----------


## ansius

moš noder: https://sites.google.com/site/avrasm.../2b-basic-math

baisi sen rakstīju kaut ko avr asm, patika, sapratu ka ir labi zināt bināro matemātiku, jo var vienkāršas darbības efektīvāk izpildīt. Tagad vairs gan nav vajadzības, nav tik kritiskas aplikācijas arduino variācija par tēmu C tiek galā gana labi. Priekšš gan ir viens projektiņš kur laiki ir kritiski, kameras / motion control sistēma kur vai nu jāliek jaudīgs procis, vai jāraksta efektīvs kods.

----------


## Jurkins

Jāsaka, es guvu patiesu gandarījumu, kad manis rakstītais asma kods (protams, ka piemērus skatījos) lika darboties 1-wire termometram, LCD displejam, 4x4 klaviatūrai un sūtīja no parastās izejas uz kompja COM portu datus (pie tam pareizus datus  :: ). Vēl neko gatavu neesmu uztaisījis uz atmeļiem(nu izņemot vienu mazu daiktiņu šķīvīšu šaušanai, bet to var neskaitīt), pagaidām tas ir tīri hobijs. Bet gan jau tiksim arī līdz C un C++.
Dabūju neta plašumos vienu grāmatiņas pēdēefu "Hacker's Delight"  - ar hakeriem nekādu sakaru, ellišķīgas lietas par bināro matemātiku. Tagad cenšos iebraukt laiku pa laikam. Linku gan vairs nepateikšu. 5 megas sver.

----------


## M_J

Par to, kā strādā katra komanda īsi, konkrēti un izsmeļoši ir AVR STUDIO "helpos".

----------


## sharps

> Dabūju neta plašumos vienu grāmatiņas pēdēefu "Hacker's Delight"  - ar hakeriem nekādu sakaru, ellišķīgas lietas par bināro matemātiku. Tagad cenšos iebraukt laiku pa laikam. Linku gan vairs nepateikšu. 5 megas sver.


 Šis?
http://ptgmedia.pearsoncmg.com/image...0321842685.pdf

skatījos ir arī otrais izlaidums.

----------


## Jurkins

Jā, man laikam bija pirmais. Nočekošu. Ja kas, paldies par otro izlaidumu.

----------


## Jurkins

Svieciens atkal šajā tēmā.
Gan ne tik daudz par asmu. Problēma sekojoša. Mans mazais kverplis dabū no DS18B20 temperatūru, salīdzina ar potenciometra (ar ADC) vērtību un attiecīgi ieslēdz/izslēdz slodzi (LEDu). Bet tam visam pa vidu no vienīgās atlikušās kājas sūta uz datora COM portu temperatūru. Nu un lai būtu cmuki pielieku galā grādu zīmīti - 176 ASCII kods un "C" burtu. Tā grāda vietā uz Putty ir ķeburs. Gan jau kaut kur vajadzīgs kāds ķeksis, bet kur. It kā viss ir  - 9600bodi , 8 biti, bez paritātes, viens stopbits un bez flow control.

----------


## ansius

gan jau ka kodu tabulas nesapas, paskaties te piem. http://serverfault.com/questions/475...led-characters

----------


## Jurkins

Paldies! Šim nepatika utf-8.

----------


## Jurkins

Netaisīšu jaunu topiku. Pajautāšu tepat.
Vakar spēlējos ar 328-to CLOCK PRESCALER.


```
ldi r16, (1<<CLKPCE)     //atļauja mainīt dalītāju
out CLKPR, r16
ldi r16, (1<<CLKPS3)    //dalītājs 256
out CLKPR, r16
```

 Viss štokos, viss notiek.


```
ldi r16, (1<<CLKPCE)     //atļauja mainīt dalītāju
out CLKPR, r16
ldi r16, (1<<CLKPS2)    //dalītājs 32
out CLKPR, r16
```

 Viss štokos, viss notiek. Taimers skaita, pārtraukumi notiek.
Bet ne nolasīt čipa signatūru ne nolasīt vai ieprogrammēt čipu vai fuses vairs nevar. Programmators bļauj, ka nevar sakonektēties. Un tā diviem pēc kārtas. 12V programmatora man nav (pagaidām). Kādu laiku atpakaļ līdzīgi notikās ar attiny13, bet vairs īsti neatceros notikumu secību un toreiz visu norakstīju uz savām līkajām rokām  :: . Var jau būt, ka vēl aizvien līkas  :: .
Bet jautājums ir par to, vai kāds nav saskāries ar šādām vai līdzīgām problēmām?

----------


## karloslv

Ar šādu konkrēti ne, bet ir nācies dzīvināt ATMegu, pieliekot pie tās ārēju kvarca ģeņģeri un barojot pa CLKI. Ja pulkstenis iet, vajadzētu it kā celties...

----------


## Jurkins

Mēģināju pieslēgt vienu arduino kā 12V programmatoru un pēc datašīta uzrakstīt programmu vispirmām kārtām lai mēģinātu nolasīt fuses, bet pagaidām nesanāk. Paldies par ieteikumu ar ārējo ģeņģeri. 
Ne jau baigā škrobe par to neejošo čipu, bet nesapratne, kas notiek. Kāpēc šādas figņas, un kā no tām nākotnē izvairīties. Ar attiny arī, šķiet, bija tā, ka rakstīju kaut ko reģistros, kas avrstudio rādās pie CPU - vai nu MCUCR vai CLKPR.

----------


## M_J

Izskatās ka atmeļa sistēmas pulkstenis ir uzlikts uz tik lēnu darbību, ka programmators pie programmēšanas ar viņu grib runāties stipri ātrāk, kā atmelis spēj izpildīties. Vajadzētu arī programmatoru pārslēgt uz iespējami lēnāko variantu. Avrdude tam izmanto komandu -B. Starp citu autors ir foruma biedrs Velko. Citāts no pamācības:*-B <bitrate>*: This is for changing the bitrate, which is how fast the programmer talks to the chip. If your chip is being clocked very slowly you'll need to talk slowly to it to let it keep up. It'll be discussed later, for now don't use it.

----------


## Jurkins

Es izmantoju Extreme Burning vai Khazama caur USBASP. Abās programmās uzlikts minimālais iespējamais ātrums 500Hz. 
Lieta jau tāda, ka atmelis turpina darbināt to programmu, kas ierakstīta, un spriežot pēc visa, sistēmas pulkstenis ir kā bijis uz 8MHz un CKDIV8 fuse ir izslēgts.

----------


## M_J

Ar Extreme Burning un Khazama, ar abām esmu aplauzies. Extreme Burning neļāva neko ierakstīt Atmegas128 programmas atmiņas otrajā pusē, savukārt Khazama, mēģinot noalsīt Atmegas128 programmas atmiņu, ne tikai to nenolasa, bet piedevām vēl sačakarē tur esošo saturu. Kopš tā laika lietoju Avrdude, vai nu no komandrindas, vai no grafiskās vides AVR8 Burn-O-Mat. Uzreiz uzrakstīt vajadzīgo komandrindu ir čakarīgi, ērti to uzticēt tam Burn-O-Mat un pēc tam, iegūtajā komandrindā tikai vajadzīgās lietas piekoriģēt, piemēram ievietojot papildus komandu -B2000. Pats ar tik lielu periodu programmēt neesmu mēģinājis, tāpēc atkal citāts no viena foruma: 

Incidentally, most fischl.de derived firmware for a USBASP will go down to 0.5kHz i.e. -B2000 (2000us period)
Of course, the Chinese USBASP do not support -B# switch. They adjust SCK frequency automatically. Unfortunately this will not go to very low speeds. Probably because no one in their right mind would use very slow F_CPU.
As Jorg said, you need to use a different ISP programmer.
David.

Lai gan - kāda tam nozīme, ja jau atmelis nav samazinājis sistēmas pulksteņa ātrumu.

----------


## Jurkins

Paldies par ieteikumu. Man arī bija tā, ka viena īsti negribēja attiny rakstīt, bet otra 328-tajam fuses neprogrammēja. AVR8 Burn-O-Mat izskatās, ka dara visu un labi. Bet manu problēmu neatrisina, tāpat nevar piekonektēties. Kā jau rakstīju, problēma nav sabojātais čips, bet tas, kāpēc šis sabojājās. Rīt(šodien) mēģināšu ar 12 voltiem.

----------


## karloslv

Vēl iespēja, ka varbūt nejauši esi RST pārfūzējis uz parastu GPIO - tad gan līdzēs tikai 12V. Tas tā, minējums tumsā tikai.

Bet kopumā izskatās, Jurkin, ka Tev jāiet par testētāju — ir cilvēki, kam vienkārši ir talants atrast _slēptās fīčas_ jebkurā vietā  ::

----------


## Jurkins

Laikam vienkārši esmu kašķīgs  :: .
No  rīta sametu pa ātro uz arduino megas(patrāpījās pa rokai) 12V fuse  lasītāju. Izstaigājos, pabaudīju jauko laiku, izvēdināju galvu un ...  izskatās, ka lasa gan fuses gan lokbitus. Un visi izņemot CKDIV8 ir  defaultie. Tieši tā, kā man arī bija salikti. Lokbiti arī visi  vieninieki. Nākamais solis - tūlīt papētīšu datasītu un uztaisīšu erase  chip ar 12v. Un tad gan vairāk nezinu...

----------


## Jurkins

Nja...
Erase chip ar 12V un atmegas pacēlušās. Nez, ko tas extreme burner šām bija ierakstījis, ja fuses un lokbiti bija kārtībā. Būs jāpaspēlējās vēl ar clock prescaler.

----------


## Jurkins

Visa cita starpā (esmu kā OS - daudzuzdevumu  :: ) darbojos ar diskrētā skaļuma regulatora projektēšanu/uzlabošanu. Atteicos no koncepcijas :
"potenciometrs -> ACD -> output uz relejiem/atslēgām"
par labu:
"enkoders -> skaitītājs -> output uz relejiem/atslēgām", jo piem. pirmajā gadījumā nav iespējama distances vadība un ... nu ar to arī pietiek.
Atnāca no e-līča lētie enkoderi. Laikam jau kontaktu drebēšana ir visu mehānisko enkoderu problēma. "Tumbočkā" neatradās normāls (74C14) šmita trigeris, izmanntoju divas KP1533LA3, bet tāpat, ja to enkoderu goza lēnām, tad gadās kļūmes. Netā ir traki daudz visādu debouncing risinājumu, bet gribējās tikt pašam skaidrībā. Tad nu tapa kods:
Izmantoju PCINT0 pārtraukumus uz frontēm un, protams, divas ieejas. 
Pārtraukumā tikai uzmetu karogu un nometu pārtraukumu masku - lai, ja arī notiek kontaktu drebēšana, pārtraukums nostrādā tikai uz pirmo fronti.
Galvenajā ciklā pārbaudu karogu. Ja ir, tad pagaidu 1 ms (pietiek), nolasu portu, atstāju tikai divus vajadzīgos bitus, kurus pārnesu uz citu (enc_val) reģistru, iepriekš nobīdot tā saturu pa kreisi.
Pēc tam pārbaudu vai tā saturs atbilst enkodera vienam apgriezienam pa labi vai pa kreisi. Ja atbilst, tad attiecīgi counter +1 vai -1.


```
#define F_CPU            8000000

#define enc_A            PCINT0
#define enc_B            PCINT1
#define temp            r16
#define enc_val            r17
#define counter            r18
#define flags            r23
#define flag_pcint0        0

.macro outi
    ldi r16, @1
    .if @0 < 0x40
        out @0, r16
    .else
        sts @0, r16
    .endif
.endmacro

.org 0x0000
    rjmp start
.org 0x0006
    rjmp PCI0_vect

.include "delay.inc"
    
start:
    clr enc_val
    clr counter
    outi PCICR, (1<<PCIE0)
    outi PCMSK0, (1<<PCINT0)|(1<<PCINT1)
    outi DDRD, (1<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD3)
    sei

main:
    rcall read_encoder
    out PORTD, counter
     rjmp main    
 
//bojā r16, ekskluzīvi bojā r17, rezultāts "counter" r18
read_encoder:
    sbrs flags, flag_pcint0
    ret
    delay_ms 1
    cbr flags, (1<<flag_pcint0)
    outi PCMSK0, (1<<PCINT0)|(1<<PCINT1)
    lsl enc_val
    lsl enc_val
    in temp, PINB
    andi temp, (1<<PCINT0)|(1<<PCINT1)
    or enc_val, temp
//ch_inc:
    cpi enc_val, 0b10000111
    brne ch_dec
    cpi counter, 0x0f
    breq ch_finish
    inc counter
    ret
ch_dec:
    cpi enc_val, 0b01001011
    brne ch_finish
    tst counter
    breq ch_finish
    dec counter
ch_finish:
    ret

PCI0_vect:
    outi PCMSK0, 0x00
    sbr flags, (1<<flag_pcint0)
    reti
```

 It kā viss strādā. Bet varbūt kāds var padalīties ar saviem risinājumiem, ne obligāti koda veidā, bet konceptuāli.
Man vispār nepatīk izmantot aiztures, gribētos iztikt bez. Varbūt tā ir paranoja :: .
Vēl jautājums. Kā ir ar "kontaktu drebēšanu" optiskajiem/magnētiskajiem enkoderiem? Pašam pieredze ar šiem maza. Tajās iekārtās, ar kurām sanāk darboties, nekādu hārdvārisku debouncing risinājumu neatrodu. Vienā 1200 tiku enkoderi pieslēgti  pie Mitsubishi kontroliera caur optroniem, otrā 400 tiku enkoderi pie Omrona "high speed counter" pa taisno, trešajā 400 tiku pa taisno pie, šķiet, mūsu pašu letiņu ražojuma kontrolierīša ieejām. Par softiskiem, protams, tur nekādas infas nav.

----------


## M_J

Varbūt arī man ir paranoja. Ar traucējumiem ne nu gluži no enkodera, bet no auto apgriezienu devējiem esmu cīnījies daudz un dikti. Traucējumi, kas izpaužas kā vairākkārtīga nostrādāšanas līmeņa šķērsošana vienas reizes vietā ir parasta parādība startēšanas brīdī, it sevišķi, ja tiek izmantoti induktīvie devēji. Bet arī Holla devēji gluži brīvi no tā nav. Vaina gan parasti ir ne pašos devējos, bet nekorektā montāžā, nepareizās "zemes" izvēlēs. Izvirzīju sev uzdevumu realizēt universālu ieeju, kurai var pieslēgt jebkura veida devēju (izņemot idiotiskos "Siemens" apgriezienu devējus, kur devējs kopā ar ieejas shēmu veido augstfrekvences ģeneratoru). Līdz ar to signāla amplitūda var mainīties ļoti plašās robežās - no 0.2V startēšanas brīdī līdz 40V vai pat vairāk pie maksimālajiem apgriezieniem no induktīvā devēja, tāpat arī frekvence no 0 līdz 22,5kHz (piemēram signāls no Audi spararata, kur devējs ņem signālu no spararata zobiem, tiem pašiem, aiz kuriem starteris griež motoru un kuri šī iemesla dēļ reizēm mēdz būt nomuļlāti un signaāls no devēja draņķīgs). Tā kā signāla frekvenču diapazons ir gana plašs, tad viena fiksēta aizture nav izmantojama - kas starta brīdī ir traucējums, pie maksimālajiem apgriezieniem gluži normāls nākošais impulss. Tāpēc pirmais, ko kontrolieris dara pēc pirmā impulsa pienākšanas ja nav jau zināmi motora apgriezieni, ir sākotnējā motora apgriezienu novērtēšana. Galu galā pirmais impulss var pienākt, kad tiek ieslēgts starteris, bet var būt arī situācija, kad motors jau griežas uz lieliem apgriezieniem, bet kontrolieris kaut kāda iemesla dēļ uz mirkli ir palicis bez barošanas (gonkās tādas lietas gadās). Šeit atkal viena nianse - pirmās apmēram 0,2 sekundes pēc pirmā impulsa saņemšanas ir jāizlaiž, tas ir laiks kurā starteris motoru iegriež tiktāl, ka var jau definēt kaut kādu rotācijas ātrumu. Pēc šīm 0,2 sekundēm zināmu laiku tiek meklēts lielākais intervāls starp pienākušajiem impulsiem. Jo lielākais intervāls raksturos griešanās ātrumu, mazākais intervāls raksturos traucējumus. Ja lielākais un mazākais intervāls starp impulsiem būtiski neatšķiras - ļoti labi, tātad traucējumu nav. Bet tādēļ traucējumu filtrēšanu neatmetu. Kad jau ir zināms aptuvenais griešanās ātrums, var iestādīt traucējumu slāpēšanas intervālu. Es izmantoju divus algoritmus. Pie mazākiem apgriezieniem vienu, pie lieliem otru. Abos gadījumos izmantoju "input capture" pārtraukumu un mikrokontroliera analogo komparatoru. Bet kontrolierim analogais komparators ir viens, bet mašīnai apgriezienu devēji var būt 3: kloķvārpstas, augšējā punkta (tas tā nosacīti, jo parasti jau nesakrīt ar augšējo punktu) un sadalenes. Tāpēc pielietoju divus ārējos komparatorus. Arī "input capture", piemēram Atmega 128 ir tikai divi pārtraukumi, bet sadalenei tik precīza impulsa pienākšanas fiksācija nav nepieciešama, pietiek ar INT pārtraukumu.  Mazo apgriezienu algoritms ir sekojošs: esmu konstatējis signāla pozitīvo fronti, piefiksējis šīs frontes pienākšanas momentu. Uz zināmu laiku (tipiski ceturtdaļa no signāla perioda, bet ne vienmēr, atkarīgs no zobu ripas konfigurācijas un apgriezieniem) aizliedzu attiecīgo pārtraukumu. Kad "mirušais laiks" pagājis pārbaudu, vai ienākošais signāls joprojām ir augstā līmenī. Ja tā, tad impulss tiek atzīts par derīgu, pārslēdzu pārtraukumu nostrādāšanai no negatīvās frontes un gaidu negatīvo fronti. Pie negatīvās frontes daru to pašu un pārslēdzu pārtraukumu uz pozitīvo fronti. Aiztures pārrēķinu pēc katra zoba, motors griežas lēni, laika pietiek. Lielo apgriezienu algoritms ir vienkāršāks - apstrādāju tikai vienu no frontēm. Pēc frontes pienākšanas aizliedzu pārtraukumu uz 3/4 no signāla perioda, pēc šīm 3/4 perioda vienkārši atļauju pārtraukumu un gaidu nākošo impulsu. Aiztures vairs nerēķinu katram zobam bet retāk - atkarībā no motora griešanās ātruma. Atsevišķs stāsts ir iztrūkstošo zobu konstatēšana un emulēšana, piemēram 60-2 zobu ripas gadījumā.

----------


## Jurkins

Uhh, tagad būs man viela pārdomām. "Input capture" un analogajam komparatoram vēl neesmu ķēries klāt.

----------


## JDat

Arī Alps consumer grade enkoderi mēdz niķoties, kad čakarē. Piemēram: ir mehānisks klikšķis, uz vienu klikšķi man uzskaita 4 impulsus (pēc kvadratūras dekodēšanas). Mākslīgi lēni griežot viss saiet auzās. Tur nav tikai debounce lietas. 
Savulaik šai lietai piegāju lasot alps enkodera datasheet par bouncing lietām un meklēju idejas kā uzrakstīt īsu kvadratūras dekodera kodu.

Te ir enkodera datasheet: http://www.alps.com/prod/info/E/PDF/.../EC11/EC11.PDF
Te kvadratūras dekodera kods. Diemžēl priekš PIC, bet savulaik pārtulkoju priekš AVR ASM: http://emerald.tufts.edu/programs/mm...aryEncoder.pdf

Nu nekas. Strādāja. Gandrīz vienmēr. Kad pārāk ātri vai pārāk lēni griež, tad neskaita kā nākas, bet 90% gadījumos bija OK.

----------


## Jurkins

PIC assembleris bišķi grūtāk saprotams, ja pareizi saprotu, bez pārtraukumiem. Šis visu laiku maļ pārbaudi. Nu jā, un šis pārbauda, vai nākamā izmaiņa atšķiras par 1, es skatījos visu tikšķi (4 frontes). 
Skaļuma regulatoram jau samērā "pie kājas", ja no 10 tikšķiem viens izkrīt.
Nu jā, es speciāli darīju, lai man būtu viens inkrements/dekrements uz klikšķi nevis uz katru impulsu.

----------


## M_J

Ja jau par skaļuma regulatoriem, tad varu piebilst, ka man pavecam Sony mūzikas centram tas enkoderis ir pilnīgā pakaļā - skaļumu regulēt var tikai ar pulti, ar to regulatoru labāk nemēģināt, rezultāts nav prognozējams un var sanākt pilnīgi pretējs cerētajam. Un tas viss attīstījās pamazām, bez kādas vardarbības no manas puses, drīzāk no nelietošanas. Līdz ar to manās acīs šāds enkoderis ir absolūti neuzticama ierīce un jau defaultā izslēdzu tāda izmantošanu jebkādās savās konstrukcijās.

----------


## Jurkins

Īstenībā šie enkoderi e-līcī tika iepirkti tīri eksperimentēšanai. Sākumā bija doma izmantot kādu no tām hitrajām mikrenēm ar holla devēju masīvu. Izrādījās, ka gatavi enkoderi ar tādu iekšā maksā apmēram tikpat cik pati mikrene. Vienīgais mīnuss šajā gadījumā, ka šos griežot nav tikšķa.
Lai gan manējiem sīčiem (nu jau vairs nav sīči) datora skandām (microlab vai) kādi gadi astoņi - enkoders bez kādā problēmām, pocis jau sen būtu nonīcis.

----------


## M_J

Droši vien tie enkoderi uzticamības ziņā var būt visai plašā diapazonā, turklāt, kā tas nereti gadās kaut kads "noname" var izpogāt smalku brendu vienos vārtos. Šajā sakarībā nedaudz beztēmas, bet nevaru noturēties nepadalījies salīdzinot divus izstrādājumus ar līdzīgām funkcijām. Savajadzējās nomērīt palielu temperatūru. Ar termopāri. Un iebarot datus kontrolierim, kuram, tavu nelaimi, nav termopāra ieejas. Viss kas saistās ar termopāru pieslēgšanu kontrolierim ir diezgan dārgs. Gribējās jau šitādu:
http://www.tme.eu/lv/details/2211-00...mer/2211-0001/
bet skopums ņēma virsroku un paņēmu šādu:
http://www.tme.eu/lv/details/ar592_1...eidotaji/apar/
Pasūtot, pat īpaši neiedziļinājos visos raksturlielumos un iespējās, man pietika ka viņš konvertē termopāra signālu uz 4-20mA
Kad atnāca, papētīju smalkāk un konstatēju ka viņš konvertē visu iespējamo uz 4-20mA un nav nepieciešama nekāda atsevišķa barošana, tiek izmantoti tie paši izejas 4-20mA
Protams, attaisīju, ar domu izpētīt, kā poļi to ir uztaisījuši un varbūt vēlāk nedaudz nodarboties ar plaģiātismu. Iekšā ir viens Atmelis, un vēl šis tas, ja kādam ir interese, varu pastāstīt sīkāk.
Salīdzināšanai - šajās dienās sanāca remontēt vienu šādu nosvilinātu transduceri, bet bez temperatūras mērīšanas funkcijas un redzēt kas tam iekšā
http://schneider.thomasnet.com/item/...dules/rmcl55bd
Salīdzinājumā ar pirmo, tas otrais ir pilnīgs mēsls, toties kas par brendu!

----------


## JDat

Ja jau beztēma... Kāda tad ir atšķirība starp visiem trijiem. Kāpēc otrais ir mēsls? Kas tur mēslains? Kas iekšā "trešajam"?
Kad bija interese par termopāra digitalizēšanu bez sāpītes, atradu argusā mikreni MAX31855

----------


## Jurkins

Sāpīte gan jau tur, ka vajadzēja 4-20mA nevis SPI.
M_J, pastāsti gan, ko tie poļi viltīgu izdomājuši. Mēs kādreiz analogi "darījām to", peldēja, bet īpašu precizitāti nevajadzēja, un tas bija sen.

A bet, ja par tēmu, tad kā ir ar to "īsto kvadratūras dekoderu"? Šim viens tikšķis skaitās katra fronte, katra uzlēcošā(krītošā) fronte vai vienas ieejas uzlēcošā(krītošā) fronte? Vot ir, piemēram, 400 tikšķu enkoders. Šim uz apgriezienu ir 400 impulsi no vienas (jebkuras) izejas?

----------


## korkis

Es termopāri mērītu ar instrumentālo opampu un auksto punktu kompensētu ar Pt100, digitalizēšanai 24bit adc, tajā max3185 drošvien viņu kompensē ar diodi, mikrene interesanta, lai gan gribētos lielāku precizitātu, protams lielākai daļai cilvēku laikam precizitāte ir pietiekama.

----------


## next

> "Tumbočkā" neatradās normāls (74C14) šmita trigeris, izmanntoju divas KP1533LA3, bet tāpat, ja to enkoderu goza lēnām, tad gadās kļūmes.


 Vot nesapratu, ja Shmitu vajag un vinja nav tad ko tur LA3 var paliidzeet?
Vai kontolierim pasham nevienaa ieejaa Shmita nav?

----------


## M_J

Turpinu beztēmu:
(cita starpā mēsls ir nevis otrais bet trešais). Pirmajam tas lielais pluss ir tas, ka to ir paredzēts montēt turpat pie termopāra, mērtausta "galvā". Gari vadi, vai, vēl sliktāk, savienojumi pa vidu termopāra rādījumu precizitātei galīgi nenāk par labu. Gan pirmajam gan otrajam pluss ir tas, ka nevajag papildus barošanu - ieslēdz starp +24V un kontroliera 4-20 ieeju un kārtībā. Ar tiem minimums 4 mA tas pārveidotājs arī tiek nobarots. Otrs pluss abiem pirmajiem - visi iestādījumi glabājas tajos esošajā mikrokontrolierī, nekādas vibrācijas tiem nevar skādēt.
 Trešajam ir vajadzīga papildus barošana. Un ja izeja tiek izmantota kā strāvas izeja, tad tā pie kontroliera ir jāslēdz starp kontroliera masu un strāvas ieeju, nevis starp 24V un strāvas ieeju. Cilvēks, kas bija transduceri montējis (tas nebiju es) bija ieslēdzis tieši tā, kā nevajag. Rezultātā - transducerim izejā esošie aizsardzības stabilitroni uz īso, kontroliera strāvas ieejai rezistors, uz kura mēra sprieguma kritumu nosvilis un nekas nestrādā. Transducera izejā esošos stabilitronus izmetu ārā, kontroliera ieejā esošo rezistoru sakombinēju no tā, kas bija līdz un tā lieta, kaut neprecīzi bet aizgāja. Līdz šim akmens vairāk gan ne transducera ražotāja bet uzstādītāja dārziņā.
 Tagad par to, "kas lācīšiem vēderā". Nezinu, bet varu iedomāties, kas vēderā pirmajam, zinu, kas vēderā otrajam. Tātad otrajam izejas pusē stabiliizatora mikrene uz 5V, no 5V vēl viena uz 3V. No 5V barojas multivibrators uz CD4069, (frekvence ap 25kHz) kam izejā maziņš trafiņš, kas baro ieejas pusi. No 3V barojas barojas opamps MCP602i, kurš kontrolē shēmas patērēto strāvu. Tas multivibrators, kas taisa barošanu galvaniski atsaistītajai shēmas ieejas daļai kopā ar opampu patērē mazāk par 4mA, tāpēc paralēli visai šai padarīšanai paralēli pieslēgts mosfets, kuru vada opamps un strāva tiek palielināta līdz vajadzīgajai.
 Shēmas ieejas daļā barošanai tiek iztaisnots no trafiņa nākošais 25kHz meandrs, caur stabilizatora mikreni uztaisīti 3V kuri baro Atmegu 88 un ADC ADS1242. No atmeļa uz priekšējo panelī esošu štekerīti izvesti RX TX izvadi ierīces parametru iestādīšanai, Atmeļa taimera izejā pieslēgts optrons IS181 uz kuru tiek padots zemas frekvences (ap 50Hz), varētu būt 10 bitu precizitātes PWM, proporcionāls izejā vajadzīgajai strāvai. Izejas pusē ar CD4069 un opampa palīdzību no tā tiek iztaisīts līdzspriegums, kurš tad stūrē tos 4-20mA.
 Savukārt tam Schneider Electric briesmonim iekšā ir analogā kapsēta, kura prasa papildus barošanu. Vesela čupa apšaubāmas kvalitātes pārslēdzēju un pieskaņošanas potenciometru. Kas notiek ar tādiem potenciometriem un slēdžiem kastē, kas pakļauta nepārtrauktai vibrācijai man ir labi zināms. Ja poļu konstrukcijai abas galvaniski atsaistītās daļas uz plates ir skaidri un nepārprotami atdalītas ar vismaz 4mm atstarpi, tad Schneider briesmonim abas puses ir juku jukām, par kaut kādu droši ieturētu attālumu starp abām daļām nevar būt runas. Turklāt tas viss salodēts pļecku pļeckām, ar milzīgām lodalvas pikām, apmēram tā, kā lodēju, kad 4. klasē sāku niekoties ar radiolietām. 
 Protams, pieslēdzot, salāpīto Schneider konstatēju, ka pārveidotais lielums par kādiem 3% atšķiras no tā, kādam tam vajadzētu būt. Poļu variantā visticamāk šāda kļūda nebūtu, bet ja arī būtu, tad varētu pieslēgt datoru un ar pāris taustiņu nospiedieniem veikt vajadzīgo papildus kalibrēšanu. Schneider variantā - jājauc atkal vaļā tā kaste un uz labu laimi jāgroza pieskaņošanas potenciomeri? Nereāli. Pat ja izdotos, pēc pāris dienām vibrācijas dēļ tāpat viss būs aizpeldējis ellē.

----------


## Jurkins

> Vot nesapratu, ja Shmitu vajag un vinja nav tad ko tur LA3 var paliidzeet?
> Vai kontolierim pasham nevienaa ieejaa Shmita nav?


 Kontrolierim Šmita toč nav, ja nu vienīgi to analogo komparatoru kaut kā... bet par to es vēl neko nezinu. 
Divi loģiskie elementi un divi rezistori un sevis nomierināšanai galā trešais elements kā buferis. Vienā LA3 ir četri, bet "tumbočkā" šo lērums un bredboardā arī vietas pietiek... ņemam divas.

xmegām esot jau gatavas kvadratūras dekoderu ieejas, bet xmegas man vēl priekšā.

----------


## next

Es shitaa ar CMOSiem esmu dariijies, bet te tak TTL...

----------


## Jurkins

Nu jā, pabīdās tā histerēze, bet dļa seļskoj mestnosķi... 1533 jau ir 74LS vai 74ALS analogs, ieejas strāvas stipri mazākas kā prastajām TTL.

----------


## Jurkins

Nu jā, nav nācies no jauna kaut ko būvēt vai remontēt ar to 4-20mA, bet vispār doma forša, ka iztiekam bez barošanas. Ja opamps ar mosfetu strāvu taisa, tad viss kārtībā  :: , es jau štukoju, kā atmelis to digitāli izdara.

----------


## korkis

Un kā tam termopārim ar atmeli kompensē auksto punktu?

----------


## M_J

Nu ne jau gluži bez barošanas, galu galā transducera izejas viens vads pie +24V, otrs pie kontroliera strāvas ieejas un transducera barošanai pilnīgi pietiek ar to strāvu, tiem 4-20 mA, kas šajā ķēdē plūst. Nav vajadzīga papildus barošnas ķēde. Ja transduceris atrodas turpat skapī, kur tie 24V ir ik uz soļa, tad tam nav lielas nozīmes, bet ja tas ir pie devēja kaut kur tālu prom, tad nav tur papildus jāvelk vēl barošana. Sīkums bet patīkami. Par aukstā gala kompensāciju īpaši nepētīju, manuprāt tā nav problēma, kaut kādos atmeļos pašos bija iekšā temperatūras devējs, ja es tādu taisītu uzliktu kādu digitālo termometru no DS vai Microchip.

----------


## korkis

Oho nezināju ka atmegās ir tempsensors iekšā jaizmēģina būs šodien ar arduino papētīt viņu, lai gan nez cik tas ir precīzi, jo mikrenei temp darba laikā mainīsies

----------


## M_J

Megās nav, varbūt kādā arī ir, neesmu speciāli meklējis, bet ir attiny24, 25, 26, varbūt vēl kādos.

----------


## korkis

Atradu ka atmega 328 ir temp sensors http://playground.arduino.cc/Main/In...peratureSensor Izmēģināju arī tikt viņam klāt.

----------


## Delfins

Skaidri un gaiši rakstīts - ir iespēja apstādināt procesu, ja tava procesa vai vides faktora ietekmē čips (vai vesela sistēma bez normālas vēdināšanas) ir "gatavs cept omleti". Cita pielietojuma tam sensoram nav. Tāpat kā ikdienas PC CPU  ::

----------


## Jurkins

Mana paranoja ::  vainagojās panākumiem - "tikšķošais" enkoders vispār bez visādiem "debouncing" un bez "delay", bez LA3 un bez Šmita trigeriem.


```
#define F_CPU            8000000
#define BAUD            19200
#define UBRR            F_CPU/BAUD/16-1

#define flags                        r23
#define flag_enc0A                0    //pārtraukumi neapstrādā enkodera ieejas
#define flag_enc0B                1    //bet tikai uzmet karogus
#define flag_cnt_change         2   //karogs, ka skaitītāja vērtība izmainījusies un vajag kaut ko darīt
#define temp                        r16
#define enc0A                       r17  //viens enkodera kanāls, varētu mierigi izmantot vienu bitu, bet reģistru pietiek
#define enc0B                       r18  //otrs enkodera kanāls, varētu mierigi izmantot vienu bitu, bet reģistru pietiek
#define enc_val                     r19  //uz katru pārtraukumu iebāžam no jaunākā bita puses kanālu vērtības
#define enc_cnt                    r20  //+/-skaitītājs

.macro outi
    ldi r16, @1
    .if @0 < 0x40
        out @0, r16
    .else
        sts @0, r16
    .endif
.endmacro

.org 0x0000
    rjmp start
.org 0x0006
    rjmp PCINT0_vect
.org 0x0008
    rjmp PCINT1_vect


msg_volume: .db "volume = ", 0

start:
    // seriālais ports, lai vienkārši apskatītos
    outi UBRR0H, HIGH(UBRR)
    outi UBRR0L, LOW(UBRR)
    outi UCSR0B, (1<<TXEN0)
    outi UCSR0C, (1<<UCSZ00)|(1<<UCSZ01)
    // izejas LEDiem/relejiem
    outi DDRB, (1<<PB6)|(1<<PB7)
    outi DDRD, (1<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD5)|(1<<PD6)|(1<<PD7)
    //pārtraukumu inicializācija
    outi PCICR, (1<<PCIE0)|(1<<PCIE1)
    outi PCMSK0, (1<<PCINT0)
    outi PCMSK1, (1<<PCINT8)
    sei

main:
//check_enc0A:
    sbrs flags, flag_enc0A            //pārbaudam A kanāla karogu
    rjmp check_enc0B                 //nav, ejam uz B kanālu
    in enc0B, PINC                     //ir, ierakstam B kanāla vērtību
    andi enc0B, (1<<PCINT8)       //uzmetam masku
    ldi temp, (1<<PCINT0)           
    eor enc0A, temp                  //invertējam A kanālu
    andi enc0A, (1<<PCINT0)      //masku varbūt arī nevajag, bet...
    rjmp enc_proc                     
check_enc0B:
    sbrs flags, flag_enc0B          //tas pats ar B kanālu
    rjmp main
    in enc0A, PINB
    andi enc0A, (1<<PCINT0)
    ldi temp, (1<<PCINT8)
    eor enc0B, temp
    andi enc0B, (1<<PCINT8)
enc_proc:
    lsl enc_val                        //nobīdam pa kreisi bez pārneses iepriekšējās kanālu vērtības
    add enc_val, enc0B           //ierakstam jauno B kanāla vērtību
    lsl enc_val                       //nobīdam
    add enc_val, enc0A          //ierakstam jauno A kanāla vērtību
//check_inc:
    cpi enc_val, 0b01111000   //pārbaudam, vai abu kanālu pēdējās četras vērtības atbilst ienam tikšķim plusā 
    brne check_dec
    cpi enc_cnt, 0xFF           //pārbaudam, vai skaitītājs nav sasniedzis "griestus"
    breq end_check_enc
    inc enc_cnt                   //plusojam
    sbr flags, (1<<flag_cnt_change)    //uzmetam karogu, ka skaitītājs izmainījies
    rjmp end_check_enc                   //ejam nomest pārtraukuma karogu
check_dec:
    cpi enc_val, 0b11010010   //pārbaudam, vai abu kanālu pēdējās četras vērtības atbilst ienam tikšķim mīnusā
    brne end_check_enc
    tst enc_cnt                    //pārbaudam, vai skaitītājs nav nulle
    breq end_check_enc
    dec enc_cnt                   //skaitam nost
    sbr flags, (1<<flag_cnt_change)   //uzmetam karogu, ka skaitītājs izmainījies
end_check_enc:
    cbr flags, (1<<flag_enc0A)           //nometam abus pārtraukuma karogus
    cbr flags, (1<<flag_enc0B)           //
    sbrs flags, flag_cnt_change         //pārbaudam, vai skaitītājs mainījies
    rjmp main                                 //nē, tad ejam prom
    cbr flags, (1<<flag_cnt_change)  //nometam skaitītāja karogu
    //counter1...0 -> PB7...6            // tālāk daram ar skaitītāja vērtību, ko vajag
    mov temp, enc_cnt
    swap temp
    lsl temp
    lsl temp
    andi temp, 0b11000000
    mov r15, temp
    in temp, PORTB
    andi temp, 0b00111111
    or temp, r15
    out PORTB, temp
    //counter7...2 -> PD7...2
    mov temp, enc_cnt
    andi temp, 0b11111100
    mov r15, temp
    in temp, PORTD
    andi temp, 0b00000011
    or temp, r15
    out PORTD, temp
    //
    ldi temp, 48
    mov r5, temp    //100
    mov r4, temp    // 10
    mov r3, temp    //  1
    mov temp, enc_cnt
_c100:
    cpi temp, 100
    brlo _c10
    subi temp, 100
    inc r5
    rjmp _c100
_c10:
    cpi temp, 10
    brlo _c1
    subi temp, 10
    inc r4
    rjmp _c10
_c1:
    add r3, temp
    //
    ldi ZL, LOW(msg_volume<<1)
    ldi ZH, HIGH(msg_volume<<1)
send_msg:
    lpm temp, Z+
    tst temp
    breq send_vol
    rcall uart_sendbyte
    rjmp send_msg
send_vol:
    mov temp, r5
    rcall uart_sendbyte
    mov temp, r4
    rcall uart_sendbyte
    mov temp, r3
    rcall uart_sendbyte
    ldi temp, 10
    rcall uart_sendbyte
    ldi temp, 13
    rcall uart_sendbyte
    
    rjmp main

uart_sendbyte:
    lds r21, UCSR0A
    sbrs r21, UDRE0
    rjmp uart_sendbyte
    sts UDR0, temp
    ret

PCINT0_vect:
    outi PCMSK0, 0x00                //aizliedzam šo pārtraukumu
    outi PCMSK1, (1<<PCINT8)     //atļaujam otru pārtraukumu
    sbr flags, (1<<flag_enc0A)     //uzmetam karogu
    reti

PCINT1_vect:
    outi PCMSK1, 0x00                //aizliedzam šo pārtraukumu
    outi PCMSK0, (1<<PCINT0)     //atļaujam otru pārtraukumu
    sbr flags, (1<<flag_enc0B)     //uzmetam karogu
    reti
```

----------


## JDat

Kā strādā? Vai kāreiz izlaiž? Vai kāreiz pagriežas uz pretējo pusi?

Starp citu: ASM nav pašdokumentējoša valoda. KUR IR KOMENTĀRI?

----------


## Jurkins

Par komentāriem, vainīgs. Iekomentēšu vēlāk.
Doma tāda, ka izmantoju uz katru enkodera kanālu savu pārtraukumu, un notiekot pārtraukumam:
1. tas tiek aizliegts (inicializācijā atļauti abi, tāpēc pirmās divas frontaes pēc ieslēgšanas, reāli, pirmais tikšķis pazūd)
2. otrs tiek atļauts
3. nolasīta tiek tikai otra kanāla vērtība (kur nevar būt nekādas kontaktu drebēšanas)
4. pirmā kanāla vērtība tiek vienkārši invertēta
Reāli šādam enkoderam jādod viens pluss vai mīnuss uz vienu tikšķi. Vienā tikšķī ir visi četri kanālu stāvokļi. Es uzskatu, ka "notikums"ir noticis tikai tad, ja ir pēc kārtas notikuši visi četri kanālu stāvokļi. Ja speciāli lēni griež un mēģina apturēt tikšķa vidū, tad izlaiž. Citādi neizlaiž, atpakaļ nepagriežas nekad.

----------


## M_J

Jā, komentāri derētu gan. Tie stipri atvieglotu saprast programmu. Arī pašam, teiksim, pēc kādām nieka divām nedēļām. Reizēm skatos uz paša rakstīto un domāju - ko es tur gribēju izdarīt? Starp citu - nekur nemanu steka rādītāja inicializāciju.
p.s. sorry - apskatījos datašītā - izrādās pats nostājas uz RAM beigām

----------


## Jurkins

Iekomentēju, bļ... kāpēc tas koda logs tabulāciju jauc nost.
M_J, jā, kods ir jēls, taisnība Tev par steka inicializāciju. Lai arī pats nostājas, beigās tāpat vienmēr ierakstu, tāpat laikam nekaitē nonullēt reģistrus, lai gan arī nekad nav bijis problēmu, bet nu labais tonis :: .

----------


## M_J

Kādā vidē raksti?

----------


## Jurkins

Atmel Studio 6.2

----------


## Jurkins

Baigais jautājums sacēlās mana pēdējā koda sakarā. Tas USART tur ir ielikts tikai kā navarots, lai paskatītos. Neesmu ar šo nekad darbojies, iemetu pēc savas saprašanas un 328 atmegas datašīta. Šis raksta tipa "volume=092". Bet reizēm pa vidam gadās tukšumi, reizēm rindiņa aizskrien uz priekšu par n pozīcijām, reizēm uzmetas vienā rindā divi uzraksti, reizēm pazūd kāds simbols. Bet, ja vienā rindiņā ir 'volume=093", nākamā ar kļūdu piem. "volume=09" turpinās viss pareizi "volume=95". Un kas pats būtiskākais - iegriežu ātri enkoderu un ... zilais nāves ekrāns. Vai tiešām tik vienkārši caur emulēto COM nokaut logus?

----------


## M_J

Protams, iedziļinoties kodā, šis jautājums būtu lieks, bet slinkuma dēļ pajautāšu - vai starp sūtījumu paketēm fiziski sanāk kāda pauze, jeb atmeļa sūtījums reāli notiek nepārtraukti bez pauzēm? Ja otrais variants, tad pieļauju, ka starp momentiem, kad dators paspēj kaut ko izvadīt uz ekrāna, tiek piedzīts pilns buferis. Kas tiek darbināts uz PC, lai šito skatītos?

----------


## Jurkins

Sūtījums notiek tikai tad, ja notikums "skaitītājs izmainījies" ir noticis un, protams, tikai vienu reizi. 
Tas notiek gan ar pytty vai kā šo tur sauc gan, ja paņem arduino serial monitor.


msg_volume ir strings "volume=" flešā
r5 - simti
r4 - desmiti
r3 - vieni
nu un pēc tam 10 un 13.

----------


## Jurkins

```
    ldi ZL, LOW(msg_volume<<1)
    ldi ZH, HIGH(msg_volume<<1)
send_msg:    
    lpm temp, Z+    
    tst temp    
    breq send_vol     
    rcall uart_sendbyte     
    rjmp send_msg 
send_vol:   
    mov temp, r5  
    rcall uart_sendbyte     
    mov temp, r4     
    rcall uart_sendbyte    
    mov temp, r3    
    rcall uart_sendbyte    
    ldi temp, 10   
    rcall uart_sendbyte    
    ldi temp, 13     
    rcall uart_sendbyte
```

 velns, kas ir ar koda logu?

----------


## Jurkins

```
uart_sendbyte:
    lds r21, UCSR0A
    sbrs r21, UDRE0
    rjmp uart_sendbyte
    sts UDR0, temp
    ret
```

 gan jau, ka vajag to izvadāmo rindu iedzīt buferī un tad bišķi jāapgūst iebūvētais USART, bet mani šokē, tas zilais ekrāns. Kur tik vienkārši noklāt kompi...

----------


## karloslv

Pamēģini apsviest 10 un 13 vietām, citādi šobrīd tev iet LF + CR.

----------


## Jurkins

jop... toč :: . Paldies.

----------


## JDat

Iesaku pamēģināt realterm. Rāda ne tikai tekstu bet arī HEX kodus, ja zin kur nospiest. Noderīgs, ja vajag saprast kā uzvedas UART (tai skaitā kļūdas utml). Jāpanāk ka uz realterm nav nekādu kļūdu un dati ir tādi kādus gribas. Pēc tam jau var darboties ar putty, hipertermināli vai savu mīļāko seriālo termināli.

----------


## Kodolskiltava

> Iesaku pamēģināt realterm.


 +100500 Realterm 4 laiFF
Tieši tam ir jābūt mīļākajam terminālim. Nu, vai arī Minicomam, ja lieto linuhu.

----------


## JDat

Realterm gan nav ērts, ja grib "pačatot" ar savu "astoņķājīti (mikrokontrolieri). Kamēr jānosūta viena rindiņa testam, tikmēr ir OK. Tomēr, ja ir garāka un interaktīva saruna, piemēram, ierakstīt kaut kādu user konfigurāciju interaktīvi, tad putty utml.

----------


## Jurkins

ok, paldies. Paskatīšos, kas par zvēru un ko ēd. Ieliekot pareizi rindas beigas vairs zilo ekrānu netaisa, bet kļūdas tāpat met. īstenībā jau šeit man to seriālo vajag kā mironim kompresi, bet ņeporjadok. Bet vispār traki, ja šitā var kompi nogāzt.

----------


## JDat

Tev vēl daudz pārsteigumu priekšā.

Palaid simulatoru un pārliecinies ka:
1) bit laiks ir pareizs un atbilst 9600
2) seriālim katrs bits ir savā vietā. Iesaku 0x55 un 0xAA patternus
3) pārliecinies ka datu pointeri neaiziet ārpus plānotajām vietām (kaut kur aizmirsās DEC vai ir lieks INC)
4) sūti pareizos datus (realterm ar HEX view)
5) uzkarini uz sava interrupt
6) pabeidz seriālo bibliotēku, jo noderēs arī citos projektos/eksperimentos

----------


## Jurkins

Nu ja, tikai paša neuzmanībaun pieredzes trūkums. Kā jau vienmēr  :: . Vienkārši rinda vēl nebija noraidīta, kad ienācās nākošais pārtraukums. Aizliedzot un atļaujot pārtraukumu, viss nostājas savās vietās. Tad gan pa klikšķim ātrāk griežot tiek izlaists, bet šādam pielietojumam tas nav svarīgi. Jo vairāk, ka seriālais nav vajadzīgs. Divu ciparu izvadīšana uz kaut kāda indikatora noteikti prasīs mazāk laika. 
Vai arī seriālajam lielāku ātrumu. Vairāk par 57.6K gan nesanāk dabūt. 76.8K aiziet kļūdaini simboli, 115.2K viss vienā čupā. Dalītājs iestatās pareizais (kā datašītā).

----------


## M_J

Ja vairāk par 57.6K nesanāk, tad kaut kas nav kārtībā. Arī 115.2K iet bez kļūdām, ātrāk neesmu dzinis. Bet par ciparu maiņas ātrumu indikatorā - ir kaut kāda robeža, līdz kurai ar aci to var uztvert, ja ātrāk viss saplūst kopā.

----------


## Jurkins

Jocīgi. Pamēģināju sūtīt 0xAA un 0x55. Uz oscilogrāfa signāli vienādi. 76.8K sāk mesties kļūdas, 115.2K pilnīgs čau. Varbūt čainas USB->COM gļučī.

----------


## JDat

> Varbūt čainas USB->COM gļučī.


 Diez vai.

Savieno RX ar TX un pasūti. Redzēsi ka strādā.Apmācības nolūkos var pieslēgt oscili.
Pēc tam atrodi kļudas kodā.





> Jocīgi. Pamēģināju sūtīt 0xAA un 0x55. Uz oscilogrāfa signāli vienādi.


 Nevar būt! skaties divreiz! Divreiz!

----------


## Jurkins

Mūžu dzīvo, mūžu mācies. Sāku pētīt, ka nosūtot 0xAA kompis saņem 0xAE, tas ir 1010 vietā 1110. Nosūtot 0x55 saņem 0x59, tas ir 0101 vietā 1001. Pamainot RealTerm baudreitu uz 125000 (atmelī 115200, dalītājs pareizs, pēc datašīta) viss nostājas vietā un ļoti stabili. Laikam visa vaina tā, ka atmelis strādā no sava ģeneratora nevis no kvarca.

ps. ne jau 0xAA==0x55, bet 0x55 pie visiem baudreitiem vienāda signāla forma, tāpat 0xAA.

edit: secinājums - dajoš kvarcu! Vai arī jātaisa katram atmelim frekvences piedzīšana. Jāielien rīt būs datašītā, jāapskatās, kā šim frekvence peld atkarībā no temperatūras.

edit_1: un vēlreiz paldies par RealTerm.  Bez tā brīnuma būtu čakarējies kā mazais ezis.

----------


## JDat

Seriālis bez kvarca? Pat bez rezonatora? Pliks RC? Nu ti daeš (dajoš). Mūžu dzīvo. mūžu mācies.

Tiko uzgooglēju: http://becomingmaker.com/usi-serial-uart-attiny85/

----------


## ezis666

> Laikam visa vaina tā, ka atmelis strādā no sava ģeneratora nevis no kvarca.


 Šitas ar melniem burtiem n-tajās vietās rakstīts- datu pārraidei, ja NAV savs clk, tad kvarcs ir obligāts!. Arī esmu uz šitā sūda vienreiz uzkāpis un čakarējies.

----------


## M_J

Jā, atmelī tās iebūvētās lietas nav diez ko precīzas. Darbojoties ar ADC sapriecājos, ka atmelī ir iebūvēta sava reference 2.56V. Tas tak varen labi, un ja jau norādītas 2 zīmes aiz komata, tad jau arī ļoti precīzs. Kad sāku lietot, jutu ka ar to precizitāti tā ir, kā ir. Paskatījos datašīta beigās - johaidī, jebkura vērtība no 2.3 līdz 2.8V.

----------


## Jurkins

Nu skaidrs, ka RC nevar būt precīzs. Intereses pēc paskatīšos, kā ir ar OSCCAL un cik braukā no temperatūras. Lietotājam vulgaris ::  kaut kādā spēļmantiņā gan jau pietiek ar RC. Uz 9600 vispār nekādu problēmu. 
Nu vot, un tagad uz šiem grābekļiem esmu uzkāpis/ Jāiet meklēt nākošos :: .
A par ADC referenci man ar bija tas pats. Uzkarinu kondiķi uz kājas 328-jam un joka pēc pamērīju ...nav 2.56. Mainu kondiķi...  :: , atkal nav... Čo za h... Gūgle palīdzēja saprast.

----------

