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
Témakörök:
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   556 / 840
(#) TavIR-AVR válasza zombee hozzászólására (») Aug 24, 2013 /
 
1, Nem C. Tényleg Bascom De nem írta hogy C kell Csak a minta volt nála C...
2, 4K-ba ez a kód simán belefér...
3, Optimalizálás van.

De ha a paremfentételek nem tisztázottak, akkor bizony bármi lehet....
MicroPascal, ASM is akár


De a C nyelvben is megoldható a feladat. Egy kódnál nem a szépség számít. A működés, a hatékonyság.. Különben is amegrendelőt az érdekli, hogy működik ahogy evárja vagy sem. Szerintem ha nincs kikötve, akár bármi nyelvben is lehet (mondjuk van M2560-ra ARM emuláció ) s futhat az alatt is....
A hozzászólás módosítva: Aug 24, 2013
(#) killbill válasza zombee hozzászólására (») Aug 24, 2013 /
 
Szia!

Egyetlen apro hiba van ezzel:

Idézet:
„PC5 - A, PC4 - B, PC3 - C, PC2 - D.”


Meg kellene forgatni a biteket. Mondjuk jo sorrendben kellene bekotni a dekoder chip-et, de ha nem lehet, akkor egy 9 elemu tablazat is megteszi.. A legtobb hardver tervezesi hiba javithato szoftveresen..

A tablazat persze kiszamolhato papiron is, de azert van a C fordito es a preprocesszor, hogy szamoljanak ok. A tablazat meg azert jo, mert igy gyorsabb es rovedebb kod lesz belole.

  1. #define _X(a)  ((((a)&1)<<5) | (((a)&2)<<3) | (((a)&4)<<1) | (((a)&8) >> 1))
  2.  
  3. static char conv[] = {
  4.  _X(0), _X(1), _X(2), _X(3), _X(4), _X(5), _X(6), _X(7), _X(8), _X(9)
  5. };
  6.  
  7. #undef _X
  8.  
  9. int szam;
  10.  
  11.    ...
  12.   PORTC = conv[ szam ];
  13.   ..
(#) killbill válasza matheattila hozzászólására (») Aug 24, 2013 / 1
 
A bemeneteknel egyszeru, mert csak and-eled a port-ot a megfelelo ertekkel, es a !! operator nullabol nullat csinal, minden masbol 1-et. Azaz, ha az adott port bit 1, akkor az eredmeny is egy lesz, egyebkent meg nulla. De ha neked nem fontos, hogy 1 legyen az eredmeny, ha a port bit magasan van, akkor a ket ! nem szukseges. A logikai donteseknel csak az szamit, hogy 0 vagy nem.

  1. #define GOMB (!!(PORTC & 8))
  2.  
  3. if(GOMB == 0)
  4.   LED_ON();


A kimeneteknel mar nem ilyen egyszeru a helyzet, mert a LED = 1 ertekadasbol az 1 az 1 marad, soha nem lesz belole 8 vagy 16 vagy akarmi. A PIC fordito bitfield-ekkel hivatkozik a hardver regiszterekre, ami nagyon leegyszerusiti a dolgodat, de a forditott kod ugyanaz lesz, mintha >> eket irnal. Azon felul ez egy kicsit gányolás, mivel a C szabvany szerint a C fordito nem garantalja, hogy a bitmezok definialasakor melyik iranyba lesznek igazitva a mezok. Egy ismeretlen kornyezetben senki nem definial hardver regiszterekre bitmezoket, mert nem tudod, hogy az elso mezo a 7-es vagy a 0-s biten lesz.. Ettol persze ez meg a PIC-en mukodik, mert a C forditohoz adott header-ek a forditonak megfeleloen vannak megirva.

Mindenesetre olyat csinalhatsz, hogy pl:
  1. #define LED(x)  ((x) ? PORTC |= 1 : PORTC &= ~1)
  2.  
  3.  
  4.  LED( 1 ); // most vilagit (ha pozitiv logikas a LED)
  5.  LED( 0 ); // most meg nem
  6.  
  7.  for(;;)
  8.    LED( GOMB );  // a LED koveti a gombot


Ebbol a kodbol is ugyanaz fordul, mintha a PIC-es bitfieldek lennenek, foleg, ha optimalizal a C forditod.
A hozzászólás módosítva: Aug 24, 2013
(#) fifadani válasza killbill hozzászólására (») Aug 24, 2013 /
 
Sziasztok!
A kapcsolás próbapanelen csücsül, tehát úgy módosítom ahogy szeretném...
Csak szerettem volna megtudakolni, hogy kell le programozni.

Amit zombee írt;
  1. DDRC = 0b00111100;
  2.  
  3. uint8_t szam = 0;
  4.  
  5. for(;;)  //végtelen ciklus
  6.  
  7. {
  8.  
  9.   PORTC = szam<<2;  //mivel a PC2 a legkisebb helyiértékű kimenet a BCD kijelzőre.
  10.  
  11.   if(++szam==10) szam=0;
  12.  
  13. }

Azt értem,hogy portok iránya, végtelen ciklus. De a szám balra tolása aztán egy darab 2-es műveletet nem értem.
Az if-ben a szam-hoz hozzá ad 1-et amíg 10 nem lesz, ha igen akkor szam=0.
A balra tolásos dolgot elmagyarázzátok?
(#) matheattila válasza killbill hozzászólására (») Aug 24, 2013 /
 
Köszönöm mindenkinek a javaslatokat!
Igaz nem írtam, hogy C nyelvről lenne szó és lehetőleg AVR Studio-ban (mert a munkahelyemen az van), ezért elnézést kérek
A programok elég nagyok, csak egy néhány férne bele a 4k-ba, így a Bascom-os út nem járható.
A példáitokkal és a javaslataitokkal nagyon sokat segítettetek, mindegyik módszert kipróbálom majd.
Mégegyszer köszönöm mindegyikötöknek
(#) killbill válasza fifadani hozzászólására (») Aug 25, 2013 /
 
be ki le fel meg el át rá ide oda szét össze vissza
Ha az igekötő az ige elött áll, egybe kell írni, azaz leprogramoz.


A << 2 azt jelenti, hogy kettovel tolja balra. A << 17 meg tizenhét bittel tolja balra. Sot, mondok jobbat. Az a <<= 3; azt jelenti, hogy az 'a' valtozot harom bittel balra tolva vissza is teszi az valtozoba.

Es ez igaz minden ketoperandusu operatorra, tehat a valtozo += 10; az hozzaad a valtozohoz 10-et. (+= -= /= *= %=)
(#) csabeszq válasza matheattila hozzászólására (») Aug 25, 2013 / 1
 
AVR alatt a 4k-s program az már elég nagy és sokat is tud, kivéve, ha 3.5k adat belőle.

Vannak ökölszabályok, amiket programozásnál be kell tartani és akkor nem lesz tele a memóriád szeméttel.

- float/double lebegőpontos típusok ne legyenek
- a cos-t táblázatból számold közelítéssel, eszedbe ne jusson a beépített könyvtári rutinokkal
- malloc-ot / free-t ne használj
- ahol 8 bit elég, ott 8 bites adattípust használj (nézd meg mi lesz, ha egy for ciklusban a változót uint32-re írod át és szörnyülködj)

Maradjunk annyiban, hogy 4k-ból már egy kerti öntözőrendszert ki lehet hozni, ami egy szivattyút és mágnesszelepeket vezérel időzítővel, nedvességméréssel,...
(#) killbill válasza killbill hozzászólására (») Aug 25, 2013 /
 
A LED makroban van egy kis hiba, bocsanat. helyesen:
  1. #define LED(x)  ((x) ? (PORTC |= 1) : (PORTC &= ~1))


A fenti peldaban a LED a C port 0-as bitjen van. Ha monjuk a PB5-on lenne, akkor igy nez ki:

  1. #define LED(x)  ((x) ? (PORTB |= 1<<5) : (PORTB &= ~(1<<5)))
(#) killbill válasza matheattila hozzászólására (») Aug 25, 2013 /
 
Idézet:
„Igaz nem írtam, hogy C nyelvről lenne szó és lehetőleg AVR Studio-ban (mert a munkahelyemen az van), ezért elnézést kérek”


Dehogynem mondtad! Meg példákat is hoztál C-ben és írtad, hogy PIC C meg AVR studio.
Vagy csak én nem érzem az iróniát???
(#) matheattila válasza csabeszq hozzászólására (») Aug 25, 2013 /
 
Rendben, megfogadom a tanácsod.
Van egy projekt amit igaz nem én írtam, mert még csak nemrég dolgozok ott, ami majdnem megtölti egy ATmega32-nek a memóriáját:
  1. AVR Memory Usage
  2. ----------------
  3. Device: atmega32
  4.  
  5. Program:   24498 bytes (74.8% Full)
  6. (.text + .data + .bootloader)
  7.  
  8. Data:       1409 bytes (68.8% Full)
  9. (.data + .bss + .noinit)

Azt hiszem, hogy ez az egyik legnagyobb program ott, GPS modulról adatokat olvas, dekódolja, hőmérsékletet mér, egy teljes menüt jelenít meg soros porton a számítógépen egy Putty nevű terminál programban, ott be lehet állítani különböző paramétereket (hogy miket küldjön a kijelzőnek, hőmérséklet, szöveg, pontos idő, dátum, koordináták (GPS), sebesség, ...menetrendeket lehet beállítani, hogy melyik megálló következik, pl ha vonaton vagy autóbuszon használják a kijelzőt), a teljes belső eeprom memóriáját át lehet másolni egy külső eeprom-ba és fordítva, ezt ugyancsak abból a terminál menüből. Az egészet majd kiküldi egy 14x112 ledből álló kijelzőnek.
Röviden ennyit tud, mindez 42 (c + h) állományból áll.
(#) matheattila válasza killbill hozzászólására (») Aug 25, 2013 /
 
Igazad van, azok mind fel voltak tüntetve és ebből egyértelmű, hogy miben szeretném a megoldást, de attól még oda írhattam volna azt is biztos ami biztos alapon
(#) Panhard hozzászólása Aug 25, 2013 /
 
Sziasztok! Egy BMP085 légnyomásmérővel küzdök. ATMEGA328P-vel olvasom, működik is minden, kiolvassa a légnyomást, hőmérsékletet. A gond az, hogy kevesebb légnyomást mutat. pl: a mai légnyomás a met.hu szerint 1011hPa, a szenzor nekem 996-ot mér. Kettő szenzorom van, a másikkal is ennyit mér. Nem tudok rájönni a hibára, többször átnéztem mindent. Az értékszámítás a szenzor adatlapja szerint van számolva. Felrakom a programot, vethetnétek rá egy pillantást, hátha valakinek szemet szúr a hiba. Köszönöm!
  1. #include <Wire.h>
  2.  
  3. #define BMP085_ADDRESS 0x77  // I2C address of BMP085
  4. #define PCF8583_ADDRESS 0x50
  5.  
  6. const unsigned char OSS = 0;  // Oversampling Setting
  7.  
  8. // Calibration values
  9. int ac1;
  10. int ac2;
  11. int ac3;
  12. unsigned int ac4;
  13. unsigned int ac5;
  14. unsigned int ac6;
  15. int b1;
  16. int b2;
  17. int mb;
  18. int mc;
  19. int md;
  20.  
  21. float osszeg;
  22. float szaml;
  23. float atlag;
  24. float temperature;
  25.  
  26. unsigned char honap_l;
  27. unsigned char honap_h;
  28. unsigned char nap_l;
  29. unsigned char nap_h;
  30. unsigned char ora_l;
  31. unsigned char ora_h;
  32. unsigned char perc_l;
  33. unsigned char perc_h;
  34. unsigned char sec_l;
  35. unsigned char sec_h;
  36.  
  37. // b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
  38. // so ...Temperature(...) must be called before ...Pressure(...).
  39. long b5;
  40.  
  41. //-----------------------------------------
  42. void setup(){
  43.    Serial.begin(9600);
  44.    Wire.begin();
  45.  
  46.   bmp085Calibration();
  47.  
  48. }
  49.  
  50. //-----------------------------------------
  51. void loop(){
  52.  
  53.   if (szaml < 50) {
  54.      
  55.   temperature = bmp085GetTemperature(bmp085ReadUT());
  56.   osszeg += bmp085GetPressure(bmp085ReadUP());
  57.  
  58.   szaml ++;
  59.  
  60. }else{
  61.  
  62.   atlag = (osszeg / 50) / 100;
  63.   osszeg = 0;
  64.   szaml = 0;
  65.  
  66.   readtime();
  67.    
  68.   Serial.print(honap_h, 0);
  69.   Serial.print(honap_l, 0);
  70.   Serial.print(".");
  71.   Serial.print(nap_h, 0);
  72.   Serial.print(nap_l, 0);
  73.   Serial.print(" ");  
  74.   Serial.print(ora_h, 0);
  75.   Serial.print(ora_l, 0);
  76.   Serial.print(":");
  77.   Serial.print(perc_h, 0);
  78.   Serial.print(perc_l, 0);
  79. //  Serial.print(":");
  80. //  Serial.print(sec_h, 0);
  81. //  Serial.print(sec_l, 0);
  82.   Serial.print(" ");
  83.   Serial.print(temperature, 1);
  84.   Serial.print(" ");
  85.   Serial.println(atlag, 1);
  86.  
  87. }
  88.    
  89.   delay(6000);
  90.  
  91. }
  92.  
  93. //-----------------------------------------
  94.  
  95. void bmp085Calibration()
  96. {
  97.   ac1 = bmp085ReadInt(0xAA);
  98.   ac2 = bmp085ReadInt(0xAC);
  99.   ac3 = bmp085ReadInt(0xAE);
  100.   ac4 = bmp085ReadInt(0xB0);
  101.   ac5 = bmp085ReadInt(0xB2);
  102.   ac6 = bmp085ReadInt(0xB4);
  103.   b1 = bmp085ReadInt(0xB6);
  104.   b2 = bmp085ReadInt(0xB8);
  105.   mb = bmp085ReadInt(0xBA);
  106.   mc = bmp085ReadInt(0xBC);
  107.   md = bmp085ReadInt(0xBE);
  108. }
  109.  
  110. //-----------------------------------------
  111. //Ido datum olvasasa
  112. void readtime()
  113. {
  114.   sec_h = (PCF8583read(0x02) >> 4)+48;
  115.   sec_l = (PCF8583read(0x02) & 0x0f)+48;
  116.   perc_h = (PCF8583read(0x03) >> 4)+48;
  117.   perc_l = (PCF8583read(0x03) & 0x0f)+48;
  118.   ora_h = (PCF8583read(0x04) >> 4)+48;
  119.   ora_l = (PCF8583read(0x04) & 0x0f)+48;
  120.   nap_h = ((PCF8583read(0x05) >> 4) & 0x03)+48;
  121.   nap_l = (PCF8583read(0x05) & 0x0f)+48;
  122.   honap_h = ((PCF8583read(0x06) >> 4) & 0x01)+48;
  123.   honap_l = (PCF8583read(0x06) & 0x0f)+48;
  124. }
  125.  
  126. //-----------------------------------------
  127. // Calculate temperature in deg C
  128. float bmp085GetTemperature(unsigned int ut){
  129.   long x1, x2;
  130.  
  131.   x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  132.   x2 = ((long)mc << 11)/(x1 + md);
  133.   b5 = x1 + x2;
  134.  
  135.   float temp = ((b5 + 8)>>4);
  136.   temp = temp /10;
  137.  
  138.   return temp;
  139. }
  140. //-----------------------------------------
  141. // Calculate pressure given up
  142. // calibration values must be known
  143. // b5 is also required so bmp085GetTemperature(...) must be called first.
  144. // Value returned will be pressure in units of Pa.
  145. long bmp085GetPressure(unsigned long up){
  146.   long x1, x2, x3, b3, b6, p;
  147.   unsigned long b4, b7;
  148.  
  149.   b6 = b5 - 4000;
  150.   // Calculate B3
  151.   x1 = (b2 * (b6 * b6)>>12)>>11;
  152.   x2 = (ac2 * b6)>>11;
  153.   x3 = x1 + x2;
  154.   b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
  155.  
  156.   // Calculate B4
  157.   x1 = (ac3 * b6)>>13;
  158.   x2 = (b1 * ((b6 * b6)>>12))>>16;
  159.   x3 = ((x1 + x2) + 2)>>2;
  160.   b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
  161.  
  162.   b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  163.   if (b7 < 0x80000000)
  164.     p = (b7<<1)/b4;
  165.   else
  166.     p = (b7/b4)<<1;
  167.  
  168.   x1 = (p>>8) * (p>>8);
  169.   x1 = (x1 * 3038)>>16;
  170.   x2 = (-7357 * p)>>16;
  171.   p += (x1 + x2 + 3791)>>4;
  172.  
  173.   long temp = p;
  174.   return temp;
  175. }
  176.  
  177. //-----------------------------------------
  178. // Read 1 byte from the BMP085 at 'address'
  179. char bmp085Read(unsigned char address)
  180. {
  181.   unsigned char data;
  182.  
  183.   Wire.beginTransmission(BMP085_ADDRESS);
  184.   Wire.write(address);
  185.   Wire.endTransmission();
  186.  
  187.   Wire.requestFrom(BMP085_ADDRESS, 1);
  188.   while(!Wire.available())
  189.     ;
  190.  
  191.   return Wire.read();
  192. }
  193.  
  194. //-----------------------------------------
  195. // Read 2 bytes from the BMP085
  196. // First byte will be from 'address'
  197. // Second byte will be from 'address'+1
  198. int bmp085ReadInt(unsigned char address)
  199. {
  200.   unsigned char msb, lsb;
  201.  
  202.   Wire.beginTransmission(BMP085_ADDRESS);
  203.   Wire.write(address);
  204.   Wire.endTransmission();
  205.  
  206.   Wire.requestFrom(BMP085_ADDRESS, 2);
  207.   while(Wire.available()<2)
  208.     ;
  209.   msb = Wire.read();
  210.   lsb = Wire.read();
  211.  
  212.   return (int) msb<<8 | lsb;
  213. }
  214.  
  215.  
  216. //-----------------------------------------
  217. // Read the uncompensated temperature value
  218. unsigned int bmp085ReadUT(){
  219.   unsigned int ut;
  220.  
  221.   // Write 0x2E into Register 0xF4
  222.   // This requests a temperature reading
  223.   Wire.beginTransmission(BMP085_ADDRESS);
  224.   Wire.write(0xF4);
  225.   Wire.write(0x2E);
  226.   Wire.endTransmission();
  227.  
  228.   // Wait at least 4.5ms
  229.   delay(10);
  230.  
  231.   // Read two bytes from registers 0xF6 and 0xF7
  232.   ut = bmp085ReadInt(0xF6);
  233.   return ut;
  234. }
  235.  
  236.  
  237. //-----------------------------------------
  238. // Read the uncompensated pressure value
  239. unsigned long bmp085ReadUP(){
  240.  
  241.   unsigned char msb, lsb, xlsb;
  242.   unsigned long up = 0;
  243.  
  244.   // Write 0x34+(OSS<<6) into register 0xF4
  245.   // Request a pressure reading w/ oversampling setting
  246.   Wire.beginTransmission(BMP085_ADDRESS);
  247.   Wire.write(0xF4);
  248.   Wire.write(0x34 +(OSS<<6));
  249.   Wire.endTransmission();
  250.  
  251.   // Wait for conversion, delay time dependent on OSS
  252.   delay(10);
  253.  
  254.   // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  255.   msb = bmp085Read(0xF6);
  256.   lsb = bmp085Read(0xF7);
  257.   xlsb = bmp085Read(0xF8);
  258.  
  259.   up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
  260.  
  261.   return up;
  262. }
  263.  
  264. //-----------------------------------------
  265. void writeRegister(int deviceAddress, byte address, byte val) {
  266.   Wire.beginTransmission(deviceAddress); // start transmission to device
  267.   Wire.write(address);       // send register address
  268.   Wire.write(val);         // send value to write
  269.   Wire.endTransmission();     // end transmission
  270. }
  271.  
  272. int readRegister(int deviceAddress, byte address){
  273.  
  274.   int v;
  275.   Wire.beginTransmission(deviceAddress);
  276.   Wire.write(address); // register to read
  277.   Wire.endTransmission();
  278.  
  279.   Wire.requestFrom(deviceAddress, 1); // read a byte
  280.  
  281.   while(!Wire.available()) {
  282.     // waiting
  283.   }
  284.  
  285.   v = Wire.read();
  286.   return v;
  287. }
  288.  
  289. //-----------------------------------------
  290. //PCF8583 olvasasa
  291.  
  292. int PCF8583read(unsigned char address)
  293. {
  294.   unsigned char bcd;
  295.  
  296.   Wire.beginTransmission(PCF8583_ADDRESS);
  297.   Wire.write(address);
  298.   Wire.endTransmission();
  299.   Wire.requestFrom(PCF8583_ADDRESS, 1);
  300.   bcd = Wire.read();
  301.   return bcd;
  302. }
  303.  
  304. //-----------------------------------------
  305. //PCF8583 irasa
  306.  
  307. int PCF8583write(unsigned char address, unsigned char val)
  308. {
  309.   Wire.beginTransmission(PCF8583_ADDRESS);
  310.   Wire.write(address);
  311.   Wire.write(val);
  312.   Wire.endTransmission();
  313. }
(#) kendre256 válasza Panhard hozzászólására (») Aug 25, 2013 /
 
A met.hu szerintem a tengerszintre átszámított légnyomást közli. Az érzékelőd minden valószínűség szerint abszolút légnyomást mér. Ez az adott helyszín tengerszint feletti magasságától is függ. (Mikor a jelenlegi lakóhelyemre költöztem, egy légnyomásmérővel mértem meg, hogy az utcánk felső vége kb. 18-20 méterrel magasabban van, mint a házunk.) A légnyomás mellesleg az időjárási viszonyoktól is függ, frontok esetén elég nagy eltérések lehetnek egymástól pár tízkilométerre lévő, akár közel azonos magasságú helyek között is.
(#) Panhard válasza kendre256 hozzászólására (») Aug 25, 2013 /
 
Most hogy mondod, igazad van. De még írják is, hogy: Tengerszintre átszámított légnyomás. Figyelmetlen voltam. Akkor adott a feladat, át kell számolnom nekem is tengerszintre, mert mindenhol így használják. Köszi!
(#) brugo hozzászólása Aug 25, 2013 /
 
Szevasztok,
Rendelnék egy Dragon programozó-debuggert (nem Magyarországon lakom ) , miket kéne még rendeljek főleg kábelekre, csatlakozókra gondolok tüskesor stb. tehát, hogy egyszerre megkapjak mindent és ne fizessek töbször postaköltséget ?
(#) zombee válasza brugo hozzászólására (») Aug 25, 2013 /
 
Gondolom tüskesort és IC foglalatot nem árt, mert egy részét ötletes módon nem forrasztják be. Kábelből szalagkábel és szalagkábel csatlakozó. Nem baj ha többet rendelsz, avatatlan kezekben fogyó eszköz ez is...
(#) brugo válasza zombee hozzászólására (») Aug 25, 2013 /
 
Naggyából én is tudom de nem tudom hogy mi a kódja például annak a csatlakozónak ami talál a Dragon tüskesoraira vagy hogy néz ki egy olyan fogó amivel a szalagkábelre szoritok egy ilyen anya csatlakozót. A képeken úgy néz ki hogy még USB kábelt se adnak hozzá az is milyen típusú kell hogy legyen ?
(#) zombee válasza brugo hozzászólására (») Aug 25, 2013 /
 
Én speciel satuval rakom össze a szalagkábeleket, de egy kisiparos üzemben a kalapács is előkerült a törékeny cucc összepattintásakor. De készen is lehet venni szalagkábelt lengő mama fejjel...
A hozzászólás módosítva: Aug 25, 2013
(#) blackdog hozzászólása Aug 25, 2013 /
 
Sziasztok!

Van egy ilyen enkóderem: Bővebben: Link
Ezen kód alapján működésre is bírtam: Bővebben: Link

Szépen működik is csak nem értem pontosan, hogy hogyan és ebben kérem a segítségeteket, hogy világosítsatok fel.
Az én kódom:
  1. #ifndef F_CPU
  2. #define F_CPU 16000000UL
  3. #endif
  4.  
  5. #include <avr/io.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <util/delay.h>
  10. #include <avr/interrupt.h>
  11. #include <inttypes.h>
  12. #include "lcd.h"
  13.  
  14. #define PHASE_A      (PINC & 1<<PC5)
  15. #define PHASE_B      (PINC & 1<<PC4)
  16.  
  17. char enc_buf[4];
  18. volatile int8_t enc_delta;
  19. static int8_t last;
  20.  
  21. void encode_init( void )
  22.  {
  23.   int8_t new;
  24.   new = 0;
  25.   last = new;                  
  26.   enc_delta = 0;
  27.  
  28.    TCCR0A |= (1<<WGM01);
  29.    TCCR0B  |= (1<<CS01) | (1<<CS00);
  30.    OCR0A   = 254;
  31.    TIFR0  |= _BV(OCF0A);
  32.    TIMSK0 |= 1<<OCIE0A;
  33.  
  34.  }
  35.  
  36.  ISR( TIMER0_COMPA_vect )          
  37.  {
  38.    int8_t new, diff;
  39.    new = 0;
  40.  
  41.    if( PHASE_A ) new = 3;
  42.    if( PHASE_B ) new ^= 1;
  43.    
  44.    diff = last - new;
  45.  
  46.    if( diff & 1 ){        
  47.      last = new;                
  48.      enc_delta += (diff & 2) - 1;    
  49.    }
  50.  }
  51.  
  52.  int8_t encode_read( void )
  53.  {
  54.    int8_t val;
  55.  
  56.      cli();
  57.    val = enc_delta;
  58.    enc_delta &= 3;
  59.    sei();
  60.    return val >> 2;
  61.  
  62.  }
  63.  
  64. int main(void) {
  65.  
  66.  
  67. lcd_init(LCD_DISP_ON);
  68. lcd_clrscr();
  69. lcd_puts("Debug:\n");
  70.  
  71. int32_t val = 0;
  72.  
  73.   encode_init();
  74.    sei();
  75.  
  76.  
  77.         while(1) {
  78.                 val += encode_read();
  79.                 lcd_gotoxy(1,2);
  80.                 sprintf(enc_buf, "%ld",val);
  81.                             lcd_puts(enc_buf);
  82.              }
  83. }


Első kérdésem: Valóban 1ms időközönként ellenőrzi a program a bemenet állapotát?
Nem pazarlás ez a processzor időből?
Aztán:
A változó amiben az aktuális állást tárolom az int8_t viszont az LCD-re történő kiírásnál már int32_t van. És ha tekerem fel/le az enkódert nem csak -128 és +127 közötti értéket kapok vissza. Ez hogyan van?
A megszakításban a new változó működését abszolút nem értem.
Megszakítással vagy timerrel korrektebb kezelni ezt az enkódert?
Szóval működik csak bizonytalan vagyok.
A hozzászólás módosítva: Aug 25, 2013
(#) Massawa válasza brugo hozzászólására (») Aug 26, 2013 /
 
IDE csatik kellenek hozzá (10 lábu), de utánna mindenféle átalakitokat magadnak kell megcsinálnod ( protoboard) mert a másik végén már egyáltalán nem egységes a csatlakozások kivitele. Nekem is egy sereg átalakitom van 10 > 6 pinre, de abbol is van vagy 3 fajta. Ezt nem uszod meg, s szerintem inkább rendelj szalagkábelt meg egy marék 6, 10 és 16 pines csatlakozot ( mindkét tipust F és M).
A hozzászólás módosítva: Aug 26, 2013
(#) Massawa válasza Massawa hozzászólására (») Aug 26, 2013 /
 
Bocs elirtam a csati nevét, nem IDE, hanem IDC.
(#) killbill válasza blackdog hozzászólására (») Aug 26, 2013 /
 
Azt nem tudom, hogy mennyi idonkent ellenorzi, de az 1ms az teljesen normalis. Ha eleg gyorsan tekered, akkor surun jonnek ott a valtozasok. Nekem valami hasonlo ALPS encoder-hez meg annal is gyorsabb pollozasi ido jott ki.

A valtozo, amiben te tarolod a poziciot (val), az int32_t. A delta, amit az encode_read() visszaad, az valoban csak 8 bites, de arra eleg is. Mert az csak az elozo lekerdezes ota tortent elmozdulast adja mindig. AVR-en eleg draga dolog a 32 bites szamabrazolas, csak indokolt esetben hasznalnam.

A new valtozo mukodeset ugy tudod a legjobban megerteni, ha felrajzolod egy papirra az A es B jelek mozgasat az enkoder elforgatasanak fuggvenyeben (ha nincs szkopod, akkor ket LED-et rakotsz, es nezed, hogy mit csinal, amikor forgatod), es megnezed, hogy mikor milyen erteket kap a new valtozo. Azt a harom sor programot, ami kiszamolja a new valtozo erteket, azt te is vegig tudod szamolni negyszer. Vagy mondjuk kiiratod a kijelzore a ket PHASE lab erteket es a new valtozot, es akkor latod, hogy mi tortenik.

Amugy a new a tekeres iranyatol fuggoen 0-1-2-3 vagy 3-2-1-0 ertekeket vesz fel. Ha az elozo es az uj allapot kulonbsegeben az also bit 1-ben all, akkor valamerre elforgattak eggyel.
  1. diff = last - new;
  2. if(diff & 1)

A masik bit erteke pedig megmondja, hogy melyik iranyba:

  1. Egyik irany:
  2. last  new     diff = last - new
  3.  3    0           3  (00000011b)
  4.  2    3          -1  (11111111b)
  5.  1    2          -1  (11111111b)
  6.  0    1          -1  (11111111b)
  7.  
  8. masik irany
  9.  0    3         -3   (11111101b)
  10.  1    0          1   (00000001b)
  11.  2    1          1   (00000001b)
  12.  3    2          1   (00000001b)

Ha megfigyeled, a diff also bitje minden lepes utan 1, a masodik bitje pedig a lepes iranyatol fuggon vagy 1 vagy 0. Ha csak ezt a bitet hagyod meg (diff & 2) az eredmeny vagy 0 vagy 2.
Ha ebbol levonsz egyet, akkor vagy -1 vagy 1 lesz az eredmeny. Es ezt adja a delta-hoz, igy az egyik iranyba mindig eggyel csokkenti a deltat, a masik iranyba meg mindig noveli.
Hogy aztan a vegen miert kell ezt neggyel elosztani (delta >> 2), azt nem tudom, de feltetelezem, azert, mert 1 enkoder lepeshez tobb fazisvaltas is tartozik. Ismerni kellene az enkoder pontos mukodeset, de az adatlapjabol szamomra nem derul ki egyertelmuen.
(#) brugo válasza Massawa hozzászólására (») Aug 26, 2013 /
 
Köszönöm szépen a tanácsokat .
(#) blackdog válasza killbill hozzászólására (») Aug 26, 2013 /
 
Köszönöm a kielégítő választ!
Kérdések:
Idézet:
„AVR-en eleg draga dolog a 32 bites szamabrazolas, csak indokolt esetben hasznalnam.”

Akkor használhatnék akár mindenhol int8_t típust?

Amire még nem jöttem rá az, hogy hogyan tudom LCD-re kiírni ezeknek a változóknak a tartalmát?
A hozzászólás módosítva: Aug 26, 2013
(#) vzoole válasza blackdog hozzászólására (») Aug 26, 2013 /
 
Ha biztos vagy benne, hogy a változód nem vesz fel -128-nál kisebb és 127-nél nagyobb értéket akkor használd. Ha nem kell negatív érték használhatsz előjel nélküli változót is.
uint8_t 0..255-ig vehet fel értéket.


8 bites előjeles változó már nem vesz fel 128-as értéket.
Értéktartomány: -128..127
Ilyenkor az első bit az előjel, és a maradék 7 biten megy a számábrázolás.

Max értéke: 0111'1111 (64+32+16+8+4+2+1 = 127)
Ha itt hozzáadsz még egyet akkor 1000'0000 (-128) eredményt kapsz.

Itt már kicsit érdekesebb, mert ahol 1 lesz azt kell hozzáadni a -128-hoz, hogy meg kapd az eredményt. Pl.: 1000'0001 (-128+1 = -127)

Ahhoz, hogy LCD-re kiírd a számokat át kell konvertálni karakterré, amihez a sprintf függvény kell.
Itt volt róla szó: Bővebben: Link
(#) blackdog válasza vzoole hozzászólására (») Aug 26, 2013 /
 
Köszönöm.
A kiírást eddig is megoldottam, de nem tudom formázni:
  1. lcd_gotoxy(1,2);
  2.                 sprintf(enc_buf, "%d",val);
  3.                 lcd_puts(enc_buf);

Ebben a formában összecsúsznak a számok idővel. Nem tudom jobban megfogalmazni.
Én viszont jobbra rendezve szeretném látni.
(#) killbill válasza blackdog hozzászólására (») Aug 27, 2013 /
 
Idézet:
„Akkor használhatnék akár mindenhol int8_t típust?”

Nem. De nem is azt mondtam, hogy ne hasznalj mast, hanem azt, hogy a 32 bites dolgok dragak AVR-en. Az AVR egy 8 bites processzor, aminek vannak 16 bites szamolasokra alkalmas utasitasai. A 32 bites muveleteket viszont eleg nehezkesen lehet vele megoldani. Ezert mondtam, hogy csak indokolt esetben hasznalnam. Az indokolt eset meg azt jelenti, hogy olyan ertekkel dolgozol, ami nem fer el 8 vagy 16 biten. Ahogy azt vzoole is irta, az int8 -128..127, az uint8 0..255 kozotti ertekek tarolasara elegendo. 16 biten mar 65536 kulonbozo ertek irhato le. int16: -32768..32767, mig az elojel nelkuli 16 bites uint16_t eseten 0..65535. Ha ez sem eleg, mert a feleadat ugy kivanja, akkor lehet hasznalni 32 bites tipust. Ha nem egesz szamokkal kell dolgozni, akkor jonnek a lebegopontos szamok, a float es a double. Ezek 32 ill. 64 bitesek (utobbiban nem vagyok biztos AVR gcc eseten). Ezekkel lenyegesen lassabban szamol, mint az eddigi egesz tipusokkal, viszont igen nagy tartomanyban irhatok le vele szamok, es nem mellesleg tortszamok is.

Bar meg kell emliteni, hogy ez a temakor nem AVR, hanem 'C'.
(#) csabeszq válasza matheattila hozzászólására (») Aug 27, 2013 /
 
Amiket itt leírtál, az már első hallásra is több, mint 4k.

Igazából arról beszéltem, hogy AVR alatt a 4k az nem kevés. Nagyon sok feladat megoldható vele (persze van, amihez 256k sem elég).

Nálam a 4k azért fontos, mert az Atmega48p a legolcsóbb mega chip. Amit lehet, arra írok, amit nem, azt Atmega328P-re.
(#) matheattila válasza csabeszq hozzászólására (») Aug 27, 2013 /
 
Értem.
Mi a munkahelyen ATmega8, ATmega16 ill. ATmega32-vel foglalkozunk, és azokban bőven van hely
(#) blackdog válasza matheattila hozzászólására (») Aug 27, 2013 /
 
Látom ment itt a "vita" a kód méretről és AVR-ről.
Az egyik kódomban ami alapból 8187byte volt az egyik int változót módosítottam char-ra. Igazából nincs más szerepe mint 1 vagy 0. Lényegében logikai változóként használom.
A lefordított kód viszont ilyen minimális változás mellett is 8130 byte-ra csökkent.
Elgondolkodtam a kód optimalizáláson. Hogyan működik ez, mi kell hozzá?
Bár eddig nem méret gondjaim voltak hanem I/O láb szám gondok. De ezeken már felül kerekedtem.
Következő: »»   556 / 840
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem