This shows you the differences between two versions of the page.
pm:prj2023:alucaci:cyclocomputer [2023/05/26 22:41] bogdan_gabriel.toma [Bibliografie/Resurse] |
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 * 3 * 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> | + | |
- | ===== Concluzii ===== | + | 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) | ||
- | ===== Download ===== | + | Cunoscand aceste date, putem aplica regula de 3 simpla pentru a afla caloriile arse pentru diferite unghiuri de panta sau kilograme astfel: |
- | <note warning> | + | ---- |
- | O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului: surse, scheme, etc. Un 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**. | + | caloriile arse 3 ori mai mult ... 1.72 unghi |
- | </note> | + | |
- | ===== Jurnal ===== | + | calorii arse de x ori mai mult ... y unghi (furnizat de giroscop) |
- | <note tip> | + | ---- |
- | Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. | + | |
- | </note> | + | |
- | ===== Bibliografie/Resurse ===== | + | 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 ===== | ||
+ | |||
+ | 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 ===== | ||
+ | {{: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://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]] | [[https://cdn.sparkfun.com/datasheets/Sensors/Accelerometers/RM-MPU-6000A.pdf|MPU-6050 Datasheet]] | ||
+ | |||
[[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]] | [[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]] | ||
+ | |||
+ | [[https://keisan.casio.com/exec/system/1350958587|Cycling calories burned calculator]] | ||
+ | |||
+ | [[https://mountainpassessouthafrica.co.za/news/facebook/item/449-conversion-table-to-ratio-to-degrees.html|Slope to degrees table]] | ||
+ | |||
+ | [[https://www.healthline.com/health/mens-health/average-weight-for-men#average-weight-around-the-world|Average height / weight men]] | ||
+ | |||
+ | [[https://www.healthline.com/health/womens-health/average-height-for-women|Average height / weight women]] | ||
+ | |||
+ | [[https://www.archtoolbox.com/calculating-slope/|Slope grade formulas]] | ||
<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> | ||