//-----------------------------------------------------------------
// 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 <Arduino.h>
#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)
float temperature,humidity;
int adc_value,pwm_value;
uint32_t duration_us,distance_cm;
String datestr,timestr;
String indicator = "";
String str1="", str2="";
Adafruit_NeoPixel pixels( 8, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
LiquidCrystal_I2C lcd( LCD_I2C_ADDR, 16, 2 );
DHT dht(DHT_PIN, DHT_TYPE);
RTC_DS1307 rtc; // Adafruit RTClib uses 0x68 as the default address.
void setup() {
/*
xTaskCreate(
taskOne, / Task function. /
"TaskOne", / String with name of task. /
10000, / Stack size in bytes. /
NULL, / Parameter passed as input of the task /
1, / Priority of the task. /
NULL); / Task handle. /
*/
// xTaskCreate(data_dht, "Read DHT22", 300, NULL, 1, NULL);
// xTaskCreate(data_read_update_pwm, "Read PWM", 128, NULL, 1, NULL);
// xTaskCreate(data_distance, "Read Distance", 128, NULL, 1, NULL);
// xTaskCreate(data_neopixels, "Read Neopixels", 128, NULL, 1, NULL);
xTaskCreate(data_rtc, "Read RTC", 100, NULL, 1, NULL);
xTaskCreate(data_display, "Display", 100, NULL, 1, NULL);
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 );
pixels.begin(); // Initialize Neopixel ring
pixels.clear(); // Clear Neopixel ring
lcd.init(); // Initialize LCD display
lcd.backlight(); // Turn on LCD backlight
Wire.setClock(400000);
dht.begin();
rtc.begin();
if (!rtc.isrunning()) { // use compilation time to set date and time for RTC
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void data_dht(void *pvParameters) {
//Read DHT22 (temperature and relative humidity)
while(1) {
temperature = dht.readTemperature();
humidity = dht.readHumidity();
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
void data_read_update_pwm(void *pvParameters) {
while(1){
adc_value = analogRead( AIN_PIN );
pwm_value = adc_value / 4;
analogWrite( PWM_PIN, pwm_value );
}
}
void data_distance(void *pvParameters) {
while(1){
//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 data_neopixels(void *pvParameters) {
// String indicator = "";
while(1){
for (int i = 0; i < 8; i++) {
uint8_t level = (pwm_value + 16) / 32;
uint8_t onoff = (i < level);
indicator += onoff ? '>' : ' ';
pixels.setPixelColor(i, onoff ?
pixels.Color(200,0,0) :
pixels.Color(0,0,0) );
}
pixels.show();
}
}
void data_rtc(void *pvParameters) {
while (1) {
DateTime time = rtc.now();
datestr = time.timestamp(DateTime::TIMESTAMP_DATE);
timestr = time.timestamp(DateTime::TIMESTAMP_TIME);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void data_display(void *pvParameters) {
while (1) {
str1 = String("Date: ") + datestr;
str2 = String("Time: ") + timestr;
// str1 = " Temp.[C]: ";
// str2 = "Humid.[%]: ";
// if (!isnan(temperature) && !isnan(humidity)) {
// str1 += temperature;
// str2 += humidity;
// } else {
// str1 += "---";
// str2 += "---";
// }
lcd.clear();
lcd.setCursor(0, 0);
lcd.print( str1.c_str() );
lcd.setCursor(0, 1);
lcd.print( str2.c_str() );
// lcd.print("eieie ");
// Serial.println("P" );
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void loop() {
// static uint8_t disp_mode = 0;
// // 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
// }
// 2) Send a Trigger pulse
// digitalWrite(TRIG_PIN, HIGH);
// delayMicroseconds(20);
// digitalWrite(TRIG_PIN, LOW);
// Measure a pulse width
// uint32_t duration_us = pulseIn(ECHO_PIN, HIGH, 25000 /*timeout*/ );
// uint32_t distance_cm = (duration_us / 2) * 343 / 1000;
// 3) Read a value from the analog input pin
//int adc_value = analogRead( AIN_PIN );
// 4) Update the duty cycle of PWM
//int pwm_value = adc_value / 4;
//analogWrite( PWM_PIN, pwm_value );
// 5) Update the colors of NeoPixels
// String indicator = "";
// for (int i = 0; i < 8; i++) {
// uint8_t level = (pwm_value + 16) / 32;
// uint8_t onoff = (i < level);
// indicator += onoff ? '>' : ' ';
// pixels.setPixelColor(i, onoff ?
// pixels.Color(200,0,0) :
// pixels.Color(0,0,0) );
// }
// pixels.show();
// 6) Read DHT22 (temperature and relative humidity)
//float temperature = dht.readTemperature();
//float humidity = dht.readHumidity();
// 7) Read RTC
// DateTime time = rtc.now();
// String datestr = time.timestamp(DateTime::TIMESTAMP_DATE);
// String timestr = time.timestamp(DateTime::TIMESTAMP_TIME);
// 7) Update the LCD display
// String str1="", str2="";
// switch (disp_mode) {
// case 0: // show ADC value and NeoPixel light level
// char lcd_buf[16];
// 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() );
// lcd.print("eieie");
// delay(250);
// String str1="", str2="";
// str1 = String("Date: ") + datestr;
// str2 = String("Time: ") + timestr;
// lcd.clear();
// lcd.setCursor(0, 0);
// // lcd.print( str1.c_str() );
// lcd.setCursor(0, 1);
// // lcd.print( str2.c_str() );
// lcd.print("eieie ");
// delay(250);
}
//-----------------------------------------------------------------