Fórum témák

» Több friss téma
Fórum » AVR - Miértek hogyanok
 
Témaindító: pakibec, idő: Márc 11, 2006
WinAVR / GCC alapszabályok:
1. Ha ISR-ben használsz globális változót, az legyen "volatile"
2. Soha ne érjen véget a main() függvény
3. UART/USART hibák 99,9% a rossz órajel miatt van
4. Kerüld el a -O0 optimalizációs beállítást minden áron
5. Ha nem jó a _delay időzítése, akkor túllépted a 65ms-et, vagy rossz az optimalizációs beállítás
6. Ha a PORTC-n nem működik valami, kapcsold ki a JTAG-et
Bővebben: AVR-libc FAQ
Lapozás: OK   767 / 767
(#) gerry válasza Kovidivi hozzászólására (») Pé, 7:30 /
 
Jelentősebb különbségről nem tudok. Olvastam, hogy talán az "A"-s típusok alacsonyabb feszültségről mennek. Vagyis van egy különbség a két verzió között, mármint a "P" és "A" között, hogy ha bootloader-el programozom fel a procit, akkor az "A"-s proci nem zárja le magát és akárhányszor fel lehet tölteni ugyanazt a programot, holott le csak akkor szabadna frissítést engedélyeznie, ha a feltöltendő fájl is frissül! És mint említettem a Rendelhető 644A olcsóbb is! Jeleztem a tulajdonosnak is, de ha neki így megfelel akkor nekem is. Megrendelem máshonnan.
A hozzászólás módosítva: Pé, 7:34
(#) Jax válasza csatti2 hozzászólására (») Pé, 12:47 /
 
Ez egy fordulatszám függő programozható előgyújtás vezérlőnek készül. Ezért fontos hogy a főtengelyfordulat ugye 360 fokos, egy ütemre, mivel 2T.. És a késleltetést úgy gondoltam, hogy a két jel közötti idő lenne a 360 fok és abból vonnám le a 10 fokos előgyújtást pl. Innen tudná mikor kell jelet adni a hall végfoknak.
(#) slimtomi válasza Jax hozzászólására (») Pé, 12:59 /
 
Szia Jax!
Az a gyanúm, hogy fordulatszámmérőt szeretnél építeni. Megszakítás használata itt fölösleges, ha más komolyabb feladatot nem szánsz a procinak. Ne a jelek számát számláld egy adott időtartam alatt - ez rossz bevett szokás - hanem két jel között eltelt időt kell mérned, majd ez alapján meghatároznod a percenkénti jelek számát.
RPM = 60 000 000 us / mért_idő
Amikor pl 2 sec-ig nincs jel, akkor a ford.számot nullázod, mert nyilván magától nem fog nullázódni, mivel két jel között mindig lesz eltelt idő.
Mindenképpen mikroszekundumban mérd az időt!
Ezzel a logikával 1-es pontossággal tudsz fordulatszámot mérni.
(#) slimtomi válasza Jax hozzászólására (») Pé, 13:07 /
 
Ilyet készítettem pár hete. Ha nem rendelkezel gyári szerelési könyvből származó gyújtás jelleggörbével, akkor nem tudod megcsinálni. Hozzáteszem, az előgyújtás nem csak fordulatszámfüggő, hanem terhelésfüggő is. Ezt a szívócső nyomása adja meg neked.
(#) Jax válasza slimtomi hozzászólására (») Pé, 20:48 /
 
Közelében jártál
(#) Jax válasza Jax hozzászólására (») Pé, 21:07 /
 
Bocsi, egy regényt írtam de csak két szót írt ki.. :\
Most nincs időm de majd írok!
(#) Robi98 hozzászólása Szo, 14:40 /
 
Sziasztok!

Már elég régóta kínlódok egy olyan programmal ami egy NEC protokollt használó távirányító jelét olvassa be input capture segítségével és kiírja a beolvasott eredményt a PC terminálablakjába.
Viszont nem akar sikerülni sehogy sem. ATmega16-os mikrovezérlőt használok 8Mhz-es belső órajellel és 8-as előosztással. (1MHz-el számol a Timer) Az infra vevő 38KHz-es, a távirányító pedig egy full alap car mp3-as és NEC protokollt használ. (HE Store-ból vettem)
Az interneten keresgéltem különböző C nyelvű kódokat a jel feldolgozására, de eddig sehol sem találtam olyat ami input capture-t és megszakításokat használ. Pedig fontos lenne.

Tudnátok benne segíteni? Köszönöm előre is.
Ez eddig a saját verzióm:
  1. volatile unsigned long IR=0;
  2. unsigned char start=0;
  3. unsigned char bitCount=0;
  4.  
  5.  
  6. ISR(TIMER1_CAPT_vect)
  7. {
  8.  
  9.         TCCR1B&=~(1<<CS11); //megállítjuk a számlálót
  10.  
  11.                 if(ICR1>13495 && ICR1<13505) start=1;
  12.                
  13.                 if(start)//ha már megvolt a startjel
  14.                 {
  15.                         if(ICR1>2245 && ICR1<2255)//ha egyes bit érkezett
  16.                         {
  17.                         IR|=1;
  18.                         IR=(IR<<1);
  19.                         bitCount++;
  20.                         }
  21.                        
  22.                         else if(ICR1>1115 && ICR1<1125)//ha nullás bit érkezett
  23.                         {
  24.                         IR=(IR<<1);
  25.                         bitCount++;
  26.                         }
  27.                 }
  28.  
  29.                 TCNT1=0;//számlálót nullázuk
  30.                 TCCR1B|=(1<<CS11);//elindítjuk a számlálót
  31.  
  32.                 if(bitCount==32)//ha végeztünk
  33.                         {
  34.                         bitCount=0;
  35.                         start=0;
  36.                         TCCR1B&=~(1<<CS11);//leáll a számláló
  37.                         }
  38.  
  39. }
  40.  
  41. ISR(USART_RXC_vect)
  42. {
  43. c=UDR; //az UART-al beolvasok egy karaktert
  44. }
  45.  
  46. int main(void)
  47. {
  48. stdout = &mystdout;
  49.  
  50. TCNT1=0;//a számlálót nullázuk
  51. TIMSK|=(1<<TICIE1); //a megszakítás már engedélyezve van, de a számláló még nem indult el
  52.  
  53. usart_init ( MYUBRR );
  54. sei();
  55. printf("IR remote control receiver (NEC format)\n");
  56.         while(1)
  57.         {
  58.                 if(c) //a beolvasott kód elküldése egy karakter leütésére történik
  59.                 {
  60.                 c=0;
  61.                 IR=~IR; //a kódot invertálom, azért, hogy azt kapjam vissza amit a távirányító küldött
  62.                 printf("Received command: 0x%08lx\n\n",IR);
  63.                 IR=0;
  64.                 }
  65.         }
  66. }
A hozzászólás módosítva: Szo, 14:42
(#) david10 hozzászólása Szo, 20:17 /
 
Sziasztok,
Az Atmel MCU selector-ban nézdelődtem, és találtam valami érdekeset:
Az MCU-nak 32 lába van, ebből 34 ki/bemenet. Ez hogy lehetséges?
Itt találtam.

Capture.PNG
    
(#) kendre256 válasza david10 hozzászólására (») Szo, 21:11 /
 
Ennek a típusnak négyféle tokozása van. 28, 32, 48 és 64 lábú. A kisebb lábszámú tokozásokban nincs mindegyik IO port kivezetve. Ez más Atmel típusoknál is szokott lenni. (Az MCU selector nem teljesen precíz.)
(#) david10 válasza kendre256 hozzászólására (») Szo, 22:01 /
 
Köszönöm szépen a választ! Most már értem.
(#) csatti2 válasza Robi98 hozzászólására (») Szo, 22:22 /
 
Itt egy SIRC protokollt feldolgozó könyvtár, amit még ATMEGA16U2-re írtam (input capture):
Header:
  1. #ifndef SIRC_REMOTE_H_INCLUDED
  2. #define SIRC_REMOTE_H_INCLUDED
  3.  
  4. #include <avr/io.h>
  5. #include <avr/interrupt.h>
  6.  
  7. #define SIRC_DEVICE_TV                1
  8. #define SIRC_DEVICE_VCR1              2
  9. #define SIRC_DEVICE_VCR2              3
  10. #define SIRC_DEVICE_LASERDISK         6
  11. #define SIRC_DEVICE_SURROUND          12
  12. #define SIRC_DEVICE_TUNER             16
  13. #define SIRC_DEVICE_CDPLAYER          17
  14. #define SIRC_DEVICE_EQUALIZER         18
  15.  
  16. #define SIRC_COMMAND_KEY0             0
  17. #define SIRC_COMMAND_KEY1             1
  18. #define SIRC_COMMAND_KEY2             2
  19. #define SIRC_COMMAND_KEY3             3
  20. #define SIRC_COMMAND_KEY4             4
  21. #define SIRC_COMMAND_KEY5             5
  22. #define SIRC_COMMAND_KEY6             6
  23. #define SIRC_COMMAND_KEY7             7
  24. #define SIRC_COMMAND_KEY8             8
  25. #define SIRC_COMMAND_KEY9             9
  26. #define SIRC_COMMAND_CHANNELUP        16
  27. #define SIRC_COMMAND_CHANNELDOWN      17
  28. #define SIRC_COMMAND_VOLUMEUP         18
  29. #define SIRC_COMMAND_VOLUMEDOWN       19
  30. #define SIRC_COMMAND_MUTE             20
  31. #define SIRC_COMMAND_POWER            21
  32. #define SIRC_COMMAND_RESET            22
  33. #define SIRC_COMMAND_AUDIOMODE        23
  34. #define SIRC_COMMAND_CONTRASTUP       24
  35. #define SIRC_COMMAND_CONTRASTDOWN     25
  36. #define SIRC_COMMAND_COLORUP          26
  37. #define SIRC_COMMAND_COLORDOWN        27
  38. #define SIRC_COMMAND_BRIGHTNESSUP     30
  39. #define SIRC_COMMAND_BRIGHTNESSDOWN   31
  40. #define SIRC_COMMAND_INPUT            37
  41. #define SIRC_COMMAND_BALANCELEFT      38
  42. #define SIRC_COMMAND_BALANCERIGHT     39
  43. #define SIRC_COMMAND_STANDBY          47
  44. #define SIRC_COMMAND_ANALOG                 56
  45. #define SIRC_COMMAND_INFO                       58
  46. #define SIRC_COMMAND_PIP                          91
  47. #define SIRC_COMMAND_HOME                       96
  48. #define SIRC_COMMAND_STEPRIGHT      116     // Chinese remote
  49. #define SIRC_COMMAND_STEPLEFT        117      // Chinese remote
  50.  
  51. typedef union
  52. {
  53.   struct
  54.   {
  55.     uint32_t command:7;
  56.     uint32_t address:5;
  57.   } sirc12;
  58.   struct
  59.   {
  60.     uint32_t command:7;
  61.     uint32_t address:8;
  62.   } sirc15;
  63.   struct
  64.   {
  65.     uint32_t command:7;
  66.     uint32_t address:5;
  67.     uint32_t extended:8;
  68.   } sirc20;
  69.   uint32_t val;
  70. } SIRC_t;
  71.  
  72. typedef enum
  73. {
  74.   SIRCINVALID,
  75.   SIRC12,
  76.   SIRC15,
  77.   SIRC20,
  78. } SIRC_Version_t;
  79.  
  80. typedef struct
  81. {
  82.   SIRC_t data;
  83.   SIRC_Version_t version;
  84. } SIRC_Frame_t;
  85.  
  86. // Callback function type for received IR command processing
  87. typedef void (*IRRemote_ReceivedCommandProcessor_t)(volatile SIRC_Frame_t*);
  88.  
  89. void IRRemote_Init(void);
  90.  
  91. //Callback
  92. void IRRemote_SetCallbackFunction(IRRemote_ReceivedCommandProcessor_t processor);
  93.  
  94. #endif /* SIRC_REMOTE_H_INCLUDED */


C:
  1. #include "sirc_remote.h"
  2. #include <stdio.h>
  3. #include "debug.h"
  4. #include <stdlib.h>
  5.  
  6. //#define _BV(x)  (1 << (x))
  7.  
  8. //#define DEBUG_IR
  9.  
  10. #define SIRC_MINSTART   2300
  11. #define SIRC_MAXSTART   2500
  12. #define SIRC_MINTRUE    1100
  13. #define SIRC_MAXTRUE    1300
  14. #define SIRC_MINFALSE   500
  15. #define SIRC_MAXFALSE   700
  16. #define SIRC_MINOFF     500
  17. #define SIRC_MAXOFF     700
  18.  
  19. typedef struct {
  20.         uint8_t valid:1;
  21.         uint8_t rising:1;
  22.         uint8_t received:1;
  23.         uint8_t bit;
  24. } State_t;
  25.  
  26.  
  27.  
  28. static volatile State_t _state;
  29. static volatile SIRC_Frame_t _data;
  30. // Command processor function pointer
  31. static volatile IRRemote_ReceivedCommandProcessor_t _cmdProcessor = NULL;
  32.  
  33. void IRRemote_Init(void)
  34. {
  35.         TCCR1A = 0;
  36.         TCCR1B = _BV(ICNC1) | _BV(CS11);        // Input capture noise canceling enabled, input capture at falling edge, timer 1 prescaler = 8
  37.         TCCR1C = 0;
  38.         TIMSK1 = _BV(ICIE1) | _BV(TOIE1);
  39.  
  40.         _state.valid = 0;
  41.         _state.rising = 0;
  42.         _state.received = 0;
  43. }
  44.  
  45. static void _checkIfOk(void)
  46. {
  47.         if (!_state.valid) return;
  48.         _data.version = SIRCINVALID;
  49.         switch (_state.bit) {
  50.                 case 12:
  51.                 _data.version = SIRC12;
  52.                 break;
  53.                 case 15:
  54.                 _data.version = SIRC15;
  55.                 break;
  56.                 case 20:
  57.                 _data.version = SIRC20;
  58.                 break;
  59.         }
  60.  
  61.         if ((_data.version != SIRCINVALID) && (_cmdProcessor != NULL)) _cmdProcessor(&_data);
  62. }
  63.  
  64. static void _decodeBit(uint16_t pulseWidth)
  65. {
  66.         if (!_state.valid) {
  67.                 if ((pulseWidth >= SIRC_MINSTART) && (pulseWidth <= SIRC_MAXSTART)) {
  68.                         _state.bit = 0;
  69.                         _state.valid = 1;
  70.                         _data.data.val = 0;
  71.                 }
  72.                 } else {
  73.                 if ((pulseWidth >= SIRC_MINTRUE) && (pulseWidth <= SIRC_MAXTRUE)) {
  74.                         _data.data.val += 1 << _state.bit++;
  75.                         } else if ((pulseWidth >= SIRC_MINFALSE) && (pulseWidth <= SIRC_MAXFALSE)) {
  76.                         _state.bit++;
  77.                         } else {
  78.                         _checkIfOk();
  79.                         _state.valid = 0;
  80.                 }
  81.         }
  82. }
  83.  
  84. static void _checkOff(uint16_t pulseWidth)
  85. {
  86.         if (!_state.valid) return;
  87.         if ((pulseWidth < SIRC_MINOFF) || (pulseWidth > SIRC_MAXOFF)) {
  88.                 _checkIfOk();
  89.                 _state.valid = 0;
  90.         }
  91. }
  92.  
  93. ISR(TIMER1_OVF_vect)
  94. {
  95.         #ifdef DEBUG_IR
  96.         if (_state.received) DBG_PrintLn("END");
  97.         _state.received = 0;
  98.         #endif
  99.         _checkIfOk();
  100.         _state.valid = 0;
  101.         _state.rising = 0;
  102.         TCCR1B &= ~_BV(ICES1); // Falling detection
  103. }
  104.  
  105. ISR(TIMER1_CAPT_vect)
  106. {
  107.         uint16_t counter = ICR1 / 2;
  108.         TCNT1 = 0;
  109.         #ifdef DEBUG_IR
  110.         if (!_state.received)
  111.         {
  112.                 DBG_PrintLnC("START:", LCD_YELLOW);
  113.         }
  114.         else
  115.         {
  116.                 char str[20];
  117.                 ltoa(counter, str, 10);
  118.                 DBG_PrintC(str, LCD_GREEN);
  119.                 DBG_Print(", ");
  120.         }
  121.         _state.received = 1;
  122.         #endif
  123.  
  124.         if (_state.rising) _decodeBit(counter);
  125.         else _checkOff(counter);
  126.         if (_state.rising) TCCR1B &= ~_BV(ICES1); // Falling detection
  127.         else TCCR1B |= _BV(ICES1); // Rising detection
  128.         _state.rising = !_state.rising;
  129.  
  130. }
  131.  
  132. void IRRemote_SetCallbackFunction(IRRemote_ReceivedCommandProcessor_t processor)
  133. {
  134.         _cmdProcessor = processor;
  135. }
(#) csatti2 válasza csatti2 hozzászólására (») Szo, 22:40 /
 
A működése röviden:
A sony IR protokollja többféle parancsot ismer, ezeket a parancs hossza (bitben) különbözteti meg egymástól (SIRC12, SIRC15, SIRC20). Az, hogy mi jött csak a legvégén derül ki.
A használatához, elsőként meg kell hívni a IRRemote_Init-et : ez konfigurálja az input capture-höz használt időzítőt.
Kell írni egy függvényt, ami majd feldolgozza a kapott parancsokat. Át kell adni a IRRemote_SetCallbackFunction függvénnyel a feldolgozó függvényedre mutató pointert.
pl.:
  1. void IRRemoteIncomingCommand(volatile SIRC_Frame_t* frame)
  2. {
  3. .
  4. .
  5. .
  6.         switch (frame->version) {
  7.                 case SIRC12:
  8.                 DBG_PrintC(TXT("S12 "), LCD_MAGENTA);
  9.                 ltoa(frame->data.sirc12.address, str, 10);
  10.                 DBG_PrintC(str, LCD_RED);
  11.                 DBG_Print(":");
  12.                 ltoa(frame->data.sirc12.command, str, 10);
  13.                 DBG_PrintLnC(str, LCD_GREEN);
  14.                 break;
  15.                 case SIRC15:
  16.                 DBG_PrintC(TXT("S15 "), LCD_MAGENTA);
  17.                 ltoa(frame->data.sirc15.address, str, 10);
  18.                 DBG_PrintC(str, LCD_RED);
  19.                 DBG_Print(":");
  20.                 ltoa(frame->data.sirc15.command, str, 10);
  21.                 DBG_PrintLnC(str, LCD_GREEN);
  22.                 break;
  23.                 case SIRC20:
  24.                 DBG_PrintC(TXT("S20 "), LCD_MAGENTA);
  25.                 ltoa(frame->data.sirc20.address, str, 10);
  26.                 DBG_PrintC(str, LCD_RED);
  27.                 DBG_Print(":");
  28.                 ltoa(frame->data.sirc20.command, str, 10);
  29.                 DBG_PrintC(str, LCD_GREEN);
  30.                 DBG_Print(":");
  31.                 ltoa(frame->data.sirc20.extended, str, 10);
  32.                 DBG_PrintLnC(str, LCD_YELLOW);
  33.                 break;
  34.                 default:
  35.                 break;
  36.         }
  37. .
  38. .
  39. .
  40. }

Majd:
  1. IRRemote_Init();
  2. IRRemote_SetCallbackFunction(&IRRemoteIncomingCommand);


Ez alapján szerintem már meg tudod írni a saját IR protokoll kezelődet.
(#) rolandgw válasza Robi98 hozzászólására (») 8:17 /
 
NEC
(#) Istvanpisti válasza Robi98 hozzászólására (») 8:48 /
 
Szia!
Nem írtad milyen a vevőáramköröd (pl. TSOP4838). A kész vevők fázist fordítanak, tehát, ha az adó LED működik, akkor a vevő kimenetén alacsony jelszint van.
Konkrét kódot nem írok, csak a folyamatot próbálom átvenni.
A főprogramban, a timer1 beállításánál lefutó él detektálás van beállítva. Ha jön az első lefutó él, akkor lefut az ISR(TIMER1_CAPT_vect) interrupt fv. Ekkor semmi érdekes adatot nem lehet vizsgálni, mert csak most kezdődött el az egész folyamat. Ekkor kellene nullázni a timert TCNT1=0; és beállítani a felfutó élre az input capture-t TCCR1B|=(1 << ICES1). A következő felfutó él esetén az ICP1 regiszterben lesz az előző lefutó él óta eltelt idő, majd meg kell nézni, hogy ez benne van-e a protokollnak megfelelő időablakban (a Te kódodban ez az időablak nagyon szűk, célszerű a protokollnak megfelelő időtől +- 20%-kal szélesebb ablakot figyelni). Ekkor megint nullázni kell a számlálót (TCCR1B&=~(1 << ICES1)), majd beállítani a lefutó élre való érzékenységet és így tovább. Szükség van még arra, hogy tudd, hogy éppen hol állsz a feldolgozással, emiatt kell egy olyan változó, amiben ezt követni lehet. Azt, hogy éppen felfutó, vagy lefutó élre vársz-e, el lehet dönteni a TCCR1B értékéből is.
  1. #define felfuto()   ((TCCR1B & (1<<ICES1)) ? 1 : 0) // használat if(felfuto())
  2. // a struktúra a folyamat követéséhez
  3. typedef enum
  4. {              
  5.   IR_IDLE=0,
  6.   IR_WAIT_LEADER_1,
  7.   IR_WAIT_LEADER_2,
  8.   IR_REPEAT,
  9.   IR_RECEIVE_BITS,
  10.   IR_WAIT_STOP_BIT,
  11.   IR_DATA_OK,
  12. } IR_MODE;
  13.  
  14. IR_MODE ir_mode=IR_IDLE;

Amikor beérkezik az első lefutó él ezt onnan fogod tudni, mert az ir_mode==IR_IDLE, akkor kezdődik a folyamat amit fentebb írtam. Az egészet egy switch-case szerkezetben érdemes kezelni.
  1. switch(ir_mode)
  2.         {
  3.                 case IR_IDLE:
  4.                 {
  5.                         if (!felfuto())  // az első lefutó él
  6.                         {
  7.                                 ir_mode=IR_WAIT_LEADER_1;
  8.                         }
  9.                         break;
  10.                 }
  11.                 case IR_WAIT_LEADER_1 :
  12.                 {
  13.                         if (felfuto())    // felfutó él
  14.                         {
  15.                                 if((ICP1 > IR_LEADER1_MIN) && (ICP1 < IR_LEADER1_MAX))
  16.                                 {
  17.                                         ir_mode=IR_WAIT_LEADER_2;
  18.                                 } else reset_IR(); // ha nem felel meg a vett jel a specifikációnak akkor
  19.                         }
  20.                         break;
  21.                 }.......

Célszerű még azt megcsinálni a program kód írásakor, hogy a kódban elhelyezhetsz egy változót (debug), aminek különböző értékeket adhatsz, attól függően, hogy meddig jutott el a program, és ezt a változót a főprogramból kiküldheted a soros porton keresztül, vagy akár ebbe a változóba be lehet írni először a startjel hosszát, stb, hogy érzékelni tudd, meddig jutott el a feldolgozás (ez csak addig kell, amíg a fejlesztés folyik). Ha a folyamat rendesen eljut a végéig, akkor egy változóval jelezni kell a főprogramnak, hogy készen van a vétel, pl. ir_ok=1; A főprogram ekkor kiolvassa a vett értéket, majd újra inicializálja a folyamatot, beállítja a timert, az ir_mode változót, nullázza a vett jeleket tároló változókat, az ir_ok=0; és kezdődik minden elölről.
(#) Robi98 hozzászólása 14:08 /
 
Köszönöm a segítőkész hozzászólásokat Amint több időm lesz, elolvasom őket
Következő: »»   767 / 767
Bejelentkezés

Belépés

Hirdetés
Frissek
2017. Feb, 26. Vas
15:37:15
Jelenleg 515 fő olvassa az oldalt
Online tagok:
Lapoda.hu     XDT.hu     HEStore.hu