//-----------------------------------------------------------------
// Author: RSP @KMUTNB
// Date: 2023-02-10
//-----------------------------------------------------------------
// TODO:
// 1) Add a Rotary Encoder module to change the light-level indicator
// if the ADC value at A0 pin below 16.
// 2) Rewrite code to use FreeRTOS tasks and inter-task synchronization/communication services
// Don't forget to include libraries
#include <Adafruit_NeoPixel.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <RTClib.h>
#include <Arduino_FreeRTOS.h>
#define BTN_PIN (6)
#define AIN_PIN (A0)
#define PWM_PIN (9)
#define NEOPIXEL_PIN (5)
#define ECHO_PIN (2)
#define TRIG_PIN (4)
#define DHT_PIN (8)
#define DHT_TYPE DHT22 // DHT 22 (AM2302), AM2321
// I2C pins SDA/SCL = A4/A5 pins
#define LCD_I2C_ADDR (0x27)
static uint8_t disp_mode = 0;
uint32_t duration_us = 0;
uint32_t distance_cm = 0;
float temperature = 0;
float humidity = 0;
String datestr = "";
String timestr = "";
int adc_value = 0;
int pwm_value = 0;
String indicator = "";
String str1="", str2="";
uint8_t level = 0;
uint8_t onoff = 0;
char lcd_buf[16];
void buttonCheck(void *pvParameters){
while(1){
// 1) Detect a button press to toggle LCD display mode
if (digitalRead(BTN_PIN) == LOW) {
while (!digitalRead(BTN_PIN)) {
delay(5);
}
disp_mode = (disp_mode + 1) % 4; // up to 4 modes
}
}
}
void ultrasonic(void *pvParameters){
while(1){
// 2) Send a Trigger pulse
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(20);
digitalWrite(TRIG_PIN, LOW);
// Measure a pulse width
duration_us = pulseIn(ECHO_PIN, HIGH, 25000 /*timeout*/ );
distance_cm = (duration_us / 2) * 343 / 1000;
}
}
void tempCheck(void *pvParameters){
DHT dht(DHT_PIN, DHT_TYPE);
dht.begin();
while(1){
// 6) Read DHT22 (temperature and relative humidity)
temperature = dht.readTemperature();
humidity = dht.readHumidity();
}
}
void rtc(void *pvParameters){
RTC_DS1307 rtc; // Adafruit RTClib uses 0x68 as the default address.
rtc.begin();
if (!rtc.isrunning()) { // use compilation time to set date and time for RTC
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
while(1){
// 7) Read RTC
DateTime time = rtc.now();
datestr = time.timestamp(DateTime::TIMESTAMP_DATE);
timestr = time.timestamp(DateTime::TIMESTAMP_TIME);
}
}
void lcd(void *pvParameters){
LiquidCrystal_I2C lcd( LCD_I2C_ADDR, 16, 2 );
lcd.init(); // Initialize LCD display
lcd.backlight(); // Turn on LCD backlight
while(1){
// 8) Update the LCD display
switch (disp_mode) {
case 0: // show ADC value and NeoPixel light level
sprintf( lcd_buf, "ADC: %04d (10b)", adc_value );
str1 = lcd_buf;
sprintf( lcd_buf, "LED: |%s", indicator.c_str() );
str2 = lcd_buf;
break;
case 1: // show pulse width and distance
str1 = " PW[us]: ";
str1 += duration_us;
str2 = "Dist.[cm]: ";
str2 += distance_cm / 10;
str2 += '.';
str2 += distance_cm % 10;
break;
case 2: // show temperature and relative humidity
str1 = " Temp.[C]: ";
str2 = "Humid.[%]: ";
if (!isnan(temperature) && !isnan(humidity)) {
str1 += temperature;
str2 += humidity;
} else {
str1 += "---";
str2 += "---";
}
break;
case 3:
str1 = String("Date: ") + datestr;
str2 = String("Time: ") + timestr;
break;
default:
disp_mode = 0;
break;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print( str1.c_str() );
lcd.setCursor(0, 1);
lcd.print( str2.c_str() );
delay(250);
}
}
void pwm(void *pvParameters){
Adafruit_NeoPixel pixels( 8, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
pixels.begin(); // Initialize Neopixel ring
pixels.clear(); // Clear Neopixel ring
while(1){
// 3) Read a value from the analog input pin
adc_value = analogRead( AIN_PIN );
// 4) Update the duty cycle of PWM
pwm_value = adc_value / 4;
analogWrite( PWM_PIN, pwm_value );
// 5) Update the colors of NeoPixels
indicator = "";
for (int i = 0; i < 8; i++) {
level = (pwm_value + 16) / 32;
onoff = (i < level);
indicator += onoff ? '>' : ' ';
pixels.setPixelColor(i, onoff ?
pixels.Color(200,0,0) :
pixels.Color(0,0,0) );
}
pixels.show();
}
}
void setup() {
Serial.begin(115200);
Serial.println( F("Arduino Nano Demo...") );
Serial.println( F("- Analog input reading (potentiometer)") );
Serial.println( F("- PWM LED dimming") );
Serial.println( F("- Push button") );
Serial.println( F("- LCD16x2 I2C display module") );
Serial.println( F("- 8-pixel NeoPixel RGB ring") );
Serial.println( F("- DHT22 temperature & humidity sensor") );
Serial.println( F("- RTC I2C DS1307") );
pinMode( BTN_PIN, INPUT_PULLUP );
pinMode( TRIG_PIN, OUTPUT );
pinMode( ECHO_PIN, INPUT );
pinMode( PWM_PIN, OUTPUT );
digitalWrite( TRIG_PIN, LOW );
digitalWrite( PWM_PIN, LOW );
Wire.setClock(400000);
xTaskCreate(buttonCheck,"ButtonCheck",50,NULL,1,NULL);
xTaskCreate(ultrasonic,"ultrasonic",50,NULL,1,NULL);
// xTaskCreate(tempCheck,"tempCheck",200,NULL,1,NULL);
// xTaskCreate(rtc,"Clock",145,NULL,1,NULL);
xTaskCreate(pwm,"Pulse",70,NULL,1,NULL);
xTaskCreate(lcd,"LCD",100,NULL,1,NULL);
vTaskStartScheduler();
}
void loop() {}
//-----------------------------------------------------------------