This shows you the differences between two versions of the page.
pm:prj2024:fstancu:cristian.creciun [2024/05/16 22:22] cristian.creciun [Hardware Design] |
pm:prj2024:fstancu:cristian.creciun [2024/05/27 13:47] (current) cristian.creciun |
||
---|---|---|---|
Line 46: | Line 46: | ||
===== Software Design ===== | ===== Software Design ===== | ||
+ | |||
<note tip> | <note tip> | ||
Descrierea codului aplicaţiei (firmware): | Descrierea codului aplicaţiei (firmware): | ||
- | * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) | + | * Mediu de dezvoltare: Arduino IDE |
- | * librării şi surse 3rd-party (e.g. Procyon AVRlib) | + | * Librării şi surse 3rd-party: AVRlib, Arduino standard libraries |
- | * algoritmi şi structuri pe care plănuiţi să le implementaţi | + | * Algoritmi şi structuri: |
- | * (etapa 3) surse şi funcţii implementate | + | - Comunicarea I2C cu un modul RTC (DS3231) pentru a obține timpul curent. |
+ | - Utilizarea unui senzor PIR pentru detectarea mișcării. | ||
+ | - Utilizarea unui senzor de lumină pentru a citi intensitatea luminii ambientale. | ||
+ | - Controlul unui LED RGB pentru a schimba culorile în funcție de timpul zilei și intensitatea luminii. | ||
+ | * (etapa 3) Surse şi funcţii implementate: | ||
+ | - Inițializarea și controlul magistralei I2C. | ||
+ | - Citirea datelor de la modulul RTC. | ||
+ | - Configurarea și citirea senzorilor de lumină și PIR. | ||
+ | - Controlul culorii LED-ului RGB pe baza timpului și luminii detectate. | ||
</note> | </note> | ||
+ | |||
+ | ### Codul aplicației: | ||
+ | <code cpp> | ||
+ | #include <avr/io.h> | ||
+ | #include <util/twi.h> | ||
+ | #include <Arduino.h> | ||
+ | |||
+ | #define DS3231_ADDRESS 0x68 | ||
+ | |||
+ | #define light A0 // Pin pentru senzorul de lumină | ||
+ | #define PIR_PIN 2 // Pinul D2 pentru PIR | ||
+ | |||
+ | // Pini pentru LED-ul RGB pe pini PWM | ||
+ | #define RED_PIN 3 | ||
+ | #define GREEN_PIN 5 | ||
+ | #define BLUE_PIN 6 | ||
+ | |||
+ | struct DateTime { | ||
+ | uint8_t second; | ||
+ | uint8_t minute; | ||
+ | uint8_t hour; | ||
+ | uint8_t day; | ||
+ | uint8_t date; | ||
+ | uint8_t month; | ||
+ | uint8_t year; | ||
+ | }; | ||
+ | |||
+ | void i2c_init() { | ||
+ | TWSR = 0x00; // Set prescaler to 1 | ||
+ | TWBR = 0x48; // Set bit rate register for 100kHz with 16MHz clock | ||
+ | } | ||
+ | |||
+ | void i2c_start() { | ||
+ | TWCR = (1 << TWSTA) | (1 << TWEN) | (1 << TWINT); | ||
+ | while (!(TWCR & (1 << TWINT))); | ||
+ | } | ||
+ | |||
+ | void i2c_stop() { | ||
+ | TWCR = (1 << TWSTO) | (1 << TWEN) | (1 << TWINT); | ||
+ | } | ||
+ | |||
+ | void i2c_write(uint8_t data) { | ||
+ | TWDR = data; | ||
+ | TWCR = (1 << TWEN) | (1 << TWINT); | ||
+ | while (!(TWCR & (1 << TWINT))); | ||
+ | } | ||
+ | |||
+ | uint8_t i2c_read_ack() { | ||
+ | TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWEA); | ||
+ | while (!(TWCR & (1 << TWINT))); | ||
+ | return TWDR; | ||
+ | } | ||
+ | |||
+ | uint8_t i2c_read_nack() { | ||
+ | TWCR = (1 << TWEN) | (1 << TWINT); | ||
+ | while (!(TWCR & (1 << TWINT))); | ||
+ | return TWDR; | ||
+ | } | ||
+ | |||
+ | uint8_t bcdToDec(uint8_t val) { | ||
+ | return ((val / 16 * 10) + (val % 16)); | ||
+ | } | ||
+ | |||
+ | DateTime readRTC() { | ||
+ | DateTime now; | ||
+ | |||
+ | i2c_start(); | ||
+ | i2c_write((DS3231_ADDRESS << 1) | TW_WRITE); | ||
+ | i2c_write(0x00); // Start from the register 0x00 | ||
+ | i2c_start(); | ||
+ | i2c_write((DS3231_ADDRESS << 1) | TW_READ); | ||
+ | |||
+ | now.second = bcdToDec(i2c_read_ack()); | ||
+ | now.minute = bcdToDec(i2c_read_ack()); | ||
+ | now.hour = bcdToDec(i2c_read_ack()); | ||
+ | now.day = bcdToDec(i2c_read_ack()); | ||
+ | now.date = bcdToDec(i2c_read_ack()); | ||
+ | now.month = bcdToDec(i2c_read_ack()); | ||
+ | now.year = bcdToDec(i2c_read_nack()); | ||
+ | |||
+ | i2c_stop(); | ||
+ | |||
+ | return now; | ||
+ | } | ||
+ | |||
+ | void setRGBColor(int red, int green, int blue) { | ||
+ | analogWrite(RED_PIN, red); | ||
+ | analogWrite(GREEN_PIN, green); | ||
+ | analogWrite(BLUE_PIN, blue); | ||
+ | } | ||
+ | |||
+ | void setRGBColorForTimeOfDay(int hour, int mVolt) { | ||
+ | int baseIntensity = map(mVolt, 0, 5000, 0, 255); | ||
+ | if (hour >= 6 && hour < 10) { | ||
+ | setRGBColor(baseIntensity, baseIntensity, 255); | ||
+ | } else if (hour >= 10 && hour < 16) { | ||
+ | setRGBColor(baseIntensity, baseIntensity, baseIntensity); | ||
+ | } else if (hour >= 16 && hour < 19) { | ||
+ | setRGBColor(255, map(baseIntensity, 0, 255, 165, 255), 0); | ||
+ | } else { | ||
+ | setRGBColor(255, map(baseIntensity, 0, 255, 0, 255), 0); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | i2c_init(); | ||
+ | |||
+ | // Setează pinii LED-ului RGB ca output utilizând registre | ||
+ | DDRD |= (1 << DDD3); // RED_PIN | ||
+ | DDRD |= (1 << DDD5); // GREEN_PIN | ||
+ | DDRD |= (1 << DDD6); // BLUE_PIN | ||
+ | |||
+ | // Setează pinul PIR ca input utilizând registre | ||
+ | DDRD &= ~(1 << DDD2); // PIR_PIN | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | DateTime now = readRTC(); | ||
+ | |||
+ | int pirState = PIND & (1 << PIND2); // Citește starea senzorului PIR utilizând registre | ||
+ | int lightValue = analogRead(light); // Citește valoarea senzorului de lumină | ||
+ | int mVolt = map(lightValue, 0, 1023, 0, 5000); // Mapează valoarea luminii la mVolt | ||
+ | |||
+ | if (pirState && !(now.hour >= 1 && now.hour < 8)) { | ||
+ | setRGBColorForTimeOfDay(now.hour, mVolt); // Setează culoarea LED-ului în funcție de ora zilei și luminozitate | ||
+ | } else { | ||
+ | setRGBColor(0, 0, 0); // Stinge LED-ul RGB | ||
+ | } | ||
+ | |||
+ | delay(1000); // Așteaptă o secundă înainte de a citi din nou | ||
+ | } | ||
+ | </code> | ||
===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== |