Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2023:alucaci:cyclocomputer [2023/05/26 22:39]
bogdan_gabriel.toma [Software Design]
pm:prj2023:alucaci:cyclocomputer [2023/06/02 21:31] (current)
bogdan_gabriel.toma [Concluzii]
Line 41: Line 41:
   * Arduino IDE   * Arduino IDE
   * Wokwi   * Wokwi
 +
 +Laboratoare folosite (fara GPIO):
 +  * Intreruperi
 +  * Timere / PWM
 +  * SPI
 +  * I2C
  
 Pentru inceput, functiile clasice arduino (si anume setup() si loop()) arata in felul urmator: Pentru inceput, functiile clasice arduino (si anume setup() si loop()) arata in felul urmator:
Line 46: Line 52:
 ''''​ ''''​
   void setup() {   void setup() {
-    cli(); 
     Serial.begin(9600);​     Serial.begin(9600);​
     setupButtons();​     setupButtons();​
     setupI2C();     setupI2C();
 +    initGyro();
     setupLCD();     setupLCD();
 +    cli();
     setupInterrupt();​     setupInterrupt();​
     sei();     sei();
Line 65: Line 72:
 ''''​ ''''​
  
-Acum, sa le luam pe ficare ​in parte si sa le discutam putin.+Acum, sa le luam pe fiecare ​in parte si sa le discutam putin.
  
 ''''​ ''''​
Line 82: Line 89:
 ''''​ ''''​
 Aceasta functie porneste comunicatia I2C prin initializarea Wire. Aceasta functie porneste comunicatia I2C prin initializarea Wire.
 +
 +''''​
 +  void initGyro() {
 +    Wire.beginTransmission(MPU);​
 +    Wire.write(0x3B);​
 +    Wire.endTransmission(false);​
 +    Wire.requestFrom(MPU,​ 6, true);
 +    AccX = (Wire.read() << 8 | Wire.read()) / 16384.0;
 +    AccY = (Wire.read() << 8 | Wire.read()) / 16384.0;
 +    AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0;
 +    AngleY = (atan(-1 * AccX / sqrt(pow(AccY,​ 2) + pow(AccZ, 2))) * 180 / PI) + 1.58 - 3.1;
 +  }
 +''''​
 +Aceasta functie initializeaza unghiul Y, calculandu-l folosind informatiile din accelerometru,​ nu giroscop. (abia dupa initializare intra in joc giroscopul)
  
 ''''​ ''''​
Line 147: Line 168:
           rec = false;           rec = false;
         }         }
-        else if(mode < 1)  mode++;+        else if(mode < 2)  mode++;
         else  mode = 0;         else  mode = 0;
       }       }
Line 160: Line 181:
     else if(mode == 1) {     else if(mode == 1) {
       setWheelMode();​       setWheelMode();​
 +    }
 +    else if(mode == 2){
 +      setWeightMode();​
     }     }
     if(rec) {     if(rec) {
-      seconds = ((millis() - baseTime) / 1000) % 60 - 5;+      seconds = ((millis() - baseTime) / 1000) % 60;
       minutes = (seconds / 60) % 60;       minutes = (seconds / 60) % 60;
       hours = (minutes / 60) % 24;       hours = (minutes / 60) % 24;
Line 183: Line 207:
       lcd.clear();​       lcd.clear();​
       lcd.setCursor(0,​ 0);       lcd.setCursor(0,​ 0);
-      lcd.print(String(kilometers, ​3) + " km");+      ​if(kilometers < 10) 
 +        ​lcd.print(String(kilometers, ​2) + " ​km"​);​ 
 +      else if(kilometers >= 10 && kilometers < 100) 
 +        lcd.print(String(kilometers,​ 1) + " km"​);​ 
 +      else if(kilometers >= 100 && kilometers < 1000) 
 +        lcd.print(String(kilometers,​ 0) + " km"​);​ 
 +      else  
 +        lcd.print("​999 ​km");
       lcd.setCursor(0,​ 1);       lcd.setCursor(0,​ 1);
       (hours >= 10) ? lcd.print(String(hours)) : lcd.print("​0"​ + String(hours));​       (hours >= 10) ? lcd.print(String(hours)) : lcd.print("​0"​ + String(hours));​
Line 194: Line 225:
       lcd.setCursor(6,​ 1);       lcd.setCursor(6,​ 1);
       (seconds >= 10) ? lcd.print(String(seconds)) : lcd.print("​0"​ + String(seconds));​       (seconds >= 10) ? lcd.print(String(seconds)) : lcd.print("​0"​ + String(seconds));​
-      lcd.setCursor(9, 0);+      lcd.setCursor(8, 0);
       lcd.print("​Cal"​);​       lcd.print("​Cal"​);​
-      lcd.setCursor(13, 0);+      lcd.setCursor(12, 0);
       lcd.print(String((int)calories));​       lcd.print(String((int)calories));​
       lcd.setCursor(9,​ 1);       lcd.setCursor(9,​ 1);
Line 233: Line 264:
 ''''​ ''''​
 Aceasta functie a rolul de a afisa pe LCD informatiile de interes modului 2, si anume, Set Wheel Mode. Tot aici apasarile butoanelor 2 si 3 conduc la modificarea diametrului rotii. Aceasta functie a rolul de a afisa pe LCD informatiile de interes modului 2, si anume, Set Wheel Mode. Tot aici apasarile butoanelor 2 si 3 conduc la modificarea diametrului rotii.
 +
 +''''​
 +  void setWeightMode() {
 +    if(millis() - prevTimeLCD >= 500) {
 +      lcd.clear();​
 +      lcd.setCursor(0,​ 0);
 +      lcd.print("​Weight:"​);​
 +      lcd.setCursor(0,​ 1);
 +      lcd.print(String(weight) + " cm");
 +      prevTimeLCD = millis();
 +    }
 +    if(!(PIND & (1 << PB3)) && pressedPD[3] == false) {
 +      pressedPD[3] = true;
 +      weight += 10;
 +      weightMultiplier = (1.6 * (weight / 80)) / 2;
 +    }
 +    else if(PIND & (1 << PB3)) pressedPD[3] = false;
 +    if(!(PIND & (1 << PB4)) && pressedPD[4] == false) {
 +      pressedPD[4] = true;
 +      if(wheelDiameterCm >= 10){
 +        weight -= 10;
 +        weightMultiplier = (1.6 * (weight / 80)) / 2;
 +      }
 +    }
 +    else if(PIND & (1 << PB4)) pressedPD[4] = false;
 +  }
 +''''​
 +Aceasta functie a rolul de a afisa pe LCD informatiile de interes modului 3, si anume, Set Weight Mode. Tot aici apasarile butoanelor 2 si 3 conduc la modificarea gretutatii.
  
 ''''​ ''''​
Line 258: Line 317:
       distance = (2 * 3.14 * (wheelDiameterCm / 2)) / 100000;       distance = (2 * 3.14 * (wheelDiameterCm / 2)) / 100000;
       if(rec){       if(rec){
-        kilometers += distance; +        ​if(kilometers < 1000) 
-        if(GyroAngleY ​>= 0.6) +          ​kilometers += distance; 
-          calories += distance * 32 * GyroAngleY / 1.72+        if(calories < 9999) { 
-        else if (GyroAngleY ​>= -0.6 && ​GyroAngleY ​< 0.6) +          slopeMultiplier = 3 * AngleY / 1.72; 
-          calories += distance * 32; +          if(AngleY ​>= 0.6) 
-        else +            calories += distance * 32 * slopeMultiplier ​weightMultiplier
-          calories += distance * 32 * -1 / 3 GyroAngleY / 1.72;+          else if (AngleY ​>= -0.6 && ​AngleY ​< 0.6) 
 +            calories += distance * 32; 
 +          else 
 +            calories += distance * 32 / (slopeMultiplier ​(-1)) weightMultiplier; 
 +        }
       }       }
       speedKmh = distance * 3600000/​(millis() - prevTimeKmh);​       speedKmh = distance * 3600000/​(millis() - prevTimeKmh);​
 +      if(speedKmh > 999)
 +        speedKmh = 999;
       prevTimeKmh = millis();       prevTimeKmh = millis();
       interrupt = false;       interrupt = false;
Line 272: Line 337:
   }   }
 ''''​ ''''​
-Aceasta functie calculeaza distanta, in km,  bazat pe diametrul rotii (variabile booleana **interrupt** este folosita pentru a nu avea intretuperi multiple (un fel de debouncing pentru intreruperi). Tot aici, in cazul in care inregistram (variabila **rec** este **true**) contorizam km, calculam caloriile si viteza. Calculul caloriilor se bazeaza pe date colectate din sursele ce urmeaza a fi citate mai jos, si pe regula de 3 simpla ​(pe scurt un om arde, in medie, de 3 ori mai multe calorii cand pedaleaza pe o rampa avand panta 3% (1.72 grade). De aici ne putem da seama de caloriile arse in functie de panta). Pentru calculul vitezei se tine cont de diametrul rotii si de timpul dintre 2 intreruperi. in cazul in care acesta este mai mare de 1 secunda, viteza se reseteaza folosind functia urmatoare.+Aceasta functie calculeaza distanta, in km,  bazat pe diametrul rotii (variabile booleana **interrupt** este folosita pentru a nu avea intretuperi multiple (un fel de debouncing pentru intreruperi). Tot aici, in cazul in care inregistram (variabila **rec** este **true**) contorizam km, calculam caloriile si viteza. Calculul caloriilor se bazeaza pe date colectate din sursele ce urmeaza a fi citate mai jos, si pe regula de 3 simpla. Pentru calculul vitezei se tine cont de diametrul rotii si de timpul dintre 2 intreruperi. in cazul in care acesta este mai mare de 1 secunda, viteza se reseteaza folosind functia urmatoare.
  
 ''''​ ''''​
Line 291: Line 356:
   float kilometers = 0, distance = 0;   float kilometers = 0, distance = 0;
   int hours = 0, minutes = 0, seconds = 0;   int hours = 0, minutes = 0, seconds = 0;
-  float wheelDiameterCm = 0;+  float wheelDiameterCm ​= 0, weight ​= 0;
   float calories = 0;   float calories = 0;
   int mode = 0;   int mode = 0;
Line 300: Line 365:
   bool PWMOn = false;   bool PWMOn = false;
   bool freeze = false;   bool freeze = false;
 +  float slopeMultiplier = 0, weightMultiplier = 0;
 ''''​ ''''​
-===== Rezultate Obţinute ===== 
  
-<note tip> +=== Explicatie ecuatii calorii: ===
-Care au fost rezultatele obţinute în urma realizării proiectului vostru. +
-</​note>​+
  
 +Luand ca referinta average male (175 cm, 80 kg) si o viteza medie (20 km/h) avem urmatoarele date:
 +  * calorii arse intr-un km ~= 32
 +  * calorii arse intr-o ora de ciclat pe teren plat ~= 300, calorii arse intr-o ora de ciclat in rampa de 3% (1.72 grade) ~= 900 (3 ori mai mult)
 +  * calorii arse intr-o ora de ciclat ~= 300, calorii arse intr-o ora de cicalt, de aceeasi persoana, dar kilograme duble ~= 480 (1.6 ori mai mult)
 +
 +Cunoscand aceste date, putem aplica regula de 3 simpla pentru a afla caloriile arse pentru diferite unghiuri de panta sau kilograme astfel:
 +
 +----
 +
 +caloriile arse 3 ori mai mult  ... 1.72 unghi
 +
 +calorii arse de x ori mai mult ... y unghi (furnizat de giroscop)
 +
 +----
 +
 +calorii arse de 1.6 ori mai mult ... avem de 2 ori 80 kg
 +
 +calorii arse de x ori mai mult   ... avem de y ori 80 kg
 +
 +----
 +
 +Cele doua reguli conduc la urmatoarele ecuatii:
 +  * caloriile += (distanta parcursa la o tura de roata, in km) * 32 (average calorii arse intr-un km) * ((3 * AngleY) / 1.72)
 +  * caloriile += (distanta parcura la o tura de roata, in km) * 32 (average calorii arse intr-un km) * ((1.6 * (weight / 80) / 2);
 +
 +
 +===== Rezultate Obţinute =====
 +
 +{{:​pm:​prj2023:​alucaci:​cyclocomputer_1_btoma.jpeg?​400|}}
 +{{:​pm:​prj2023:​alucaci:​cyclocomputer_2_btoma.jpeg?​400|}}
 +{{:​pm:​prj2023:​alucaci:​cyclocomputer_3_btoma.jpeg?​400|}}
 +{{:​pm:​prj2023:​alucaci:​cyclocomputer_4_btoma.jpeg?​400|}}
 +{{:​pm:​prj2023:​alucaci:​cyclocomputer_5_btoma.jpeg?​400|}}
 +{{:​pm:​prj2023:​alucaci:​cyclocomputer_6_btoma.jpeg?​400|}}
 ===== Concluzii ===== ===== Concluzii =====
  
 +In urma acestui proiect am realizat ca este mult mai usor sa te accidentezi stand la o masa decat ai crede. In saptamanile de proiect m-am accidentat cu:
 +  * Foarfeca
 +  * Letcon
 +  * Fire
 +  * Alta foarfeca
 +  * Cositor
 +  * Pini
 +Asadar, in urma instalarii unui usor PTSD la simplul contact vizual cu o unealta din campul electronicii / electrotehnicii / orice cuvant prefixat, sau sufixat, de termenul "​electro",​ am invatat sa dau importanta normelor de protectia muncii.
 +Tot in cadrul proiectului am invatat ca led-urile cumparate de la un magazin, cel putin dubios, dintr-un imobil interbelic, a carui cale de acces (usa) se afla in curtea din spate, deloc primitoare, comuna cu alte imobile invecinate, pot fi putin, putin mai mult, peste pretul de piata.
 +
 +Desigur, pe parcursul proiectului am invatat cum se configureaza un arduino folosind registri, ceea ce conduce la o viteza conisderabil mai mare a programului si la minimizarea spatiului utilizat, cum compilatorul optimizeaza codul, cum functioneaz intreruperile,​ timerele, etc.  dar asta nu este foarte important. In viata mai des te intalnesti cu o foarfeca (nu o sa o iert) decat cu un timer pe 16 biti care trebuie configurat in asa fel incat sa genereze un semnal PWM pe pinul D9 cu un duty cycle de 50%, avand frecventa nealterata (16MHz).
 +
 +Dar ca sa concluzionam,​ scurt, foarte frumos, mai facem™ :like:
 ===== Download ===== ===== Download =====
 +{{:​pm:​prj2023:​alucaci:​cyclocomputer_toma_bogdan_gabriel.rar|}}
 +
 +
 +===== Bibliografie/​Resurse[[http://​example.com|External Link]] =====
 +
 +[[https://​ww1.microchip.com/​downloads/​en/​DeviceDoc/​Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|ATmega328P Datasheet]]
 +
 +[[https://​cdn.sparkfun.com/​datasheets/​Sensors/​Accelerometers/​RM-MPU-6000A.pdf|MPU-6050 Datasheet]]
  
-<note warning>​ +[[https://www.livestrong.com/​article/​315791-calories-burned-by-biking-uphill/#:​~:​text=The%20same%20person%20traveling%20at,​nearly%20850%20calories%20per%20hour.|Calories burned cycling uphill]]
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectuluisurse, scheme, etcUn fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-).+
  
-Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:pm:​prj20??:​c?​** sau **:​pm:​prj20??:​c?:​nume_student** (dacă este cazul)**Exemplu:​** Dumitru Alin, 331CC -> **:​pm:​prj2009:​cc:​dumitru_alin**. +[[https://keisan.casio.com/​exec/​system/1350958587|Cycling calories burned calculator]]
-</note>+
  
-===== Jurnal =====+[[https://​mountainpassessouthafrica.co.za/​news/​facebook/​item/​449-conversion-table-to-ratio-to-degrees.html|Slope to degrees table]]
  
-<note tip> +[[https://​www.healthline.com/​health/​mens-health/​average-weight-for-men#​average-weight-around-the-world|Average height ​weight men]]
-Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. +
-</note>+
  
-===== Bibliografie/Resurse =====+[[https://​www.healthline.com/​health/​womens-health/​average-height-for-women|Average height / weight women]]
  
-<​note>​ +[[https://​www.archtoolbox.com/​calculating-slope/|Slope grade formulas]]
-Listă cu documente, datasheet-uri,​ resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. +
-</note>+
  
 <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​ <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​
  
pm/prj2023/alucaci/cyclocomputer.1685129942.txt.gz · Last modified: 2023/05/26 22:39 by bogdan_gabriel.toma
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0