deseu, cosul nu se va deschide si va porni alarma pentru 5 secunde.
Lista de piese: 1. Senzor Ultrasonic x2 2. Servomotor 3. Plusivo (compatibil Arduino Uno) 4. Buzzer 5. LCD 1602 cu modul I2C
Configurarea pinilor - descrisa prin MACRO-uri
#define TRIG_PIN1 2 #define ECHO_PIN1 3 #define TRIG_PIN2 4 #define ECHO_PIN2 5 #define BUZZER_PIN 9 #define SERVO_PIN 8
Conectarea la placuta plusivo a componentelor utilizate: servomotor, senzori ultrasonici si buzzer.
Initializarea componentelor
LiquidCrystal_I2C lcd(0x27, 16, 2); PWMServo myServo;
Se initializeaza obiectele pentru afisajul LCD si servomotor.
Configurarea timerului pentru generarea de intreruperi
cli(); // Dezactiveaza intreruperile // Seteaza modul timerului la CTC (Clear Timer on Compare Match) TCCR0A = (1 << WGM01); // Mod CTC cu OCR0A ca TOP // Seteaza valoarea de comparare pentru 0.15 secunde la 16 MHz OCR0A = 234; // 16e6 / (1024 * 0.15) - 1 // Activeaza intreruperea de comparare A a timerului TIMSK0 = (1 << OCIE0A); // Porneste temporizatorul cu prescaler 1024 TCCR0B = (1 << CS02) | (1 << CS00); // Prescaler 1024 sei(); // Activeaza intreruperile
Timer0 este configurat pentru a genera o intrerupere la fiecare 0,15 secunde pentru a masura distanta folosind senzorii ultrasonici. Folosirea unui timer genereaza un consum optim de energie, calculul distantelor fiind mai rar realizat.
Functia principala - LOOP
void loop() { unsigned long currentMillis = millis(); // Obtine timpul curent in milisecunde int currentDistance1; cli(); // Dezactiveaza intreruperile currentDistance1 = distance1; // Copiaza valoarea distance1 calculata // in cadrul intreruperii sei(); // Activeaza intreruperile // Gestioneaza miscarea servo-ului si alarma in bucla principala if (wasteLevel == 100 && currentDistance1 < 20 && servoState == 0) { alarm = true; // Activeaza alarma daca nivelul deseurilor este 100 si distanta este mai mica de 20 cm } else if (currentDistance1 < 20) { if (servoState == 0 && servoCounter <= 0) { myServo.write(10); // Roteste servo motorul la 10 grade servoState++; // Creste starea servo-ului servoCounter = 0; // Reseteaza contorul servo } else if (servoState == 1 && servoCounter >= 50) { myServo.write(130); // Returneaza servo motorul la pozitia initiala servoState = 0; // Reseteaza starea servo-ului } } if (wasteLevel < 100) { alarm = false; // Dezactiveaza alarma daca nivelul deseurilor este sub 100 } // Activeaza alarma daca nivelul deseurilor este 100 if (alarm) tone(BUZZER_PIN, 1000); // Start the buzzer } else { noTone(BUZZER_PIN); } // Afiseaza nivelul de deseuri pe LCD lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(wasteLevel); }
Aceasta descrie logica de control a servomotorului si a buzzerului. La fiecare 0,15 secunde se genereaza o interupere TIMER0_COMPA de tip Timer/Counter0 Compare Match A care face o recalculare a celor 2 distante folosite, distanta dintre cos si mana utilizatorului si cea dintre senzor si gunoi. Apoi, in functie de noile distante, se verifica daca este necesara deschiderii capacului, adica modificarea pozitiei servomotorului.
ISR(TIMER0_COMPA_vect) { // Recalculeaza distantele la fiecare 0.15 secunde unsigned long currentMillis = millis(); // Obtine timpul curent in milisecunde // Verifica primul senzor ultrasonic digitalWrite(TRIG_PIN1, LOW); delayMicroseconds(2); digitalWrite(TRIG_PIN1, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN1, LOW); distance1 = pulseIn(ECHO_PIN1, HIGH) * 0.034 / 2; // Calculeaza distanta in cm // Verifica al doilea senzor ultrasonic digitalWrite(TRIG_PIN2, LOW); delayMicroseconds(2); digitalWrite(TRIG_PIN2, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN2, LOW); distance2 = pulseIn(ECHO_PIN2, HIGH) * 0.034 / 2; // Calculeaza distanta in cm // Mapeaza distanta la nivelul de deseuri (100 cand cosul este plin, 0 cand este gol) wasteLevel = map(distance2, 5, 20, 100, 0); // Mapeaza distanta (5-20 cm) la nivelul de deseuri (100-0) wasteLevel = constrain(wasteLevel, 0, 100); // Asigura ca wasteLevel ramane in intervalul 0-100 // Incrementeaza contorul servo daca servo-ul este in pozitia 1 if (servoState == 1 && servoCounter < 50) { servoCounter++; } // Decrementeaza contorul servo daca servo-ul este in pozitia 0 if (servoState == 0 && servoCounter > 0) { servoCounter--; } }
prin deschiderea capacului cu ajutorul unui senzor ultrasonic care sa activeze servomotorul daca distanta este mai mica decat 20. Totodata, acesta aduce la cunostinta utilizatorului ca trebuie sa arunce gunoiul prin declansarea unei alarme cand cosul este plin.