├── ArduFarmBot2_Relay.fzz ├── ArduFarmBot2_Pin_Diagram.png ├── ArduFarmBot2_Block_Diagram.png ├── ArduFarmBot2_Ext_Auto_Ctrl__V3_0 ├── stationCredentials.h ├── stationDefines.h ├── getSensors.ino ├── generalFunctions.ino ├── oledDisplay.ino └── ArduFarmBot2_Ext_Auto_Ctrl__V3_0.ino ├── ArduFarmBot2_Ext_Auto_Ctrl__V4_0 ├── stationCredentials.h ├── stationDefines.h ├── getSensors.ino ├── generalFunctions.ino ├── oledDisplay.ino └── ArduFarmBot2_Ext_Auto_Ctrl__V4_0.ino ├── OledTest └── OledTest.ino ├── OneWire ├── keywords.txt ├── examples │ ├── DS2408_Switch │ │ └── DS2408_Switch.pde │ ├── DS18x20_Temperature │ │ └── DS18x20_Temperature.pde │ └── DS250x_PROM │ │ └── DS250x_PROM.pde ├── OneWire.h └── OneWire.cpp ├── ArduFarmBot2_Local_Manual_Ctrl_V1 ├── stationDefines.h ├── generalFunctions.ino ├── getSensors.ino ├── oledDisplay.ino └── ArduFarmBot2_Local_Manual_Ctrl_V1.ino ├── ArduFarmBot2_Local_Automatic_Ctrl_V2 ├── stationDefines.h ├── generalFunctions.ino ├── getSensors.ino ├── oledDisplay.ino └── ArduFarmBot2_Local_Automatic_Ctrl_V2.ino ├── README.md ├── DHT22_Test_with_Oled └── DHT22_Test_with_Oled.ino └── ArduFarmBot2_PartialTest └── ArduFarmBot2_PartialTest.ino /ArduFarmBot2_Relay.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mjrovai/ArduFarmBot-2/HEAD/ArduFarmBot2_Relay.fzz -------------------------------------------------------------------------------- /ArduFarmBot2_Pin_Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mjrovai/ArduFarmBot-2/HEAD/ArduFarmBot2_Pin_Diagram.png -------------------------------------------------------------------------------- /ArduFarmBot2_Block_Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mjrovai/ArduFarmBot-2/HEAD/ArduFarmBot2_Block_Diagram.png -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V3_0/stationCredentials.h: -------------------------------------------------------------------------------- 1 | char auth[] = "YOUR PROJECT TOKEN"; // Blynk project: "ArduFarmBot2" 2 | char ssid[] = "YOUR LOCAL WIFI NAME"; 3 | char pass[] = "YOUR WIFI PASSWORD"; 4 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V4_0/stationCredentials.h: -------------------------------------------------------------------------------- 1 | char auth[] = "YOUR PROJECT TOKEN"; // Blynk project: "ArduFarmBot2" 2 | char ssid[] = "YOUR LOCAL WIFI NAME"; 3 | char pass[] = "YOUR WIFI PASSWORD"; 4 | -------------------------------------------------------------------------------- /OledTest/OledTest.ino: -------------------------------------------------------------------------------- 1 | 2 | /*********************************************************************** 3 | * NodeMCU and OLED display "Hello World" 4 | * Based on original code developed by: Makerbro at https://acrobotic.com/ 5 | * MJRoBot 12Oct16 6 | ************************************************************************/ 7 | 8 | #include 9 | #include 10 | 11 | void setup() 12 | { 13 | Wire.begin(); 14 | oled.init(); // Initialze SSD1306 OLED display 15 | oled.clearDisplay(); // Clear screen 16 | oled.setTextXY(0,0); // Set cursor position, start of line 0 17 | oled.putString(" MJRoBot.org"); 18 | oled.setTextXY(4,0); // Set cursor position, start of line 4 19 | oled.putString(" HELLO, WORLD"); 20 | } 21 | 22 | void loop() 23 | { 24 | } 25 | -------------------------------------------------------------------------------- /OneWire/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For OneWire 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | OneWire KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | reset KEYWORD2 16 | write_bit KEYWORD2 17 | read_bit KEYWORD2 18 | write KEYWORD2 19 | write_bytes KEYWORD2 20 | read KEYWORD2 21 | read_bytes KEYWORD2 22 | select KEYWORD2 23 | skip KEYWORD2 24 | depower KEYWORD2 25 | reset_search KEYWORD2 26 | search KEYWORD2 27 | crc8 KEYWORD2 28 | crc16 KEYWORD2 29 | check_crc16 KEYWORD2 30 | 31 | ####################################### 32 | # Instances (KEYWORD2) 33 | ####################################### 34 | 35 | 36 | ####################################### 37 | # Constants (LITERAL1) 38 | ####################################### 39 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Manual_Ctrl_V1/stationDefines.h: -------------------------------------------------------------------------------- 1 | 2 | /* TIMER */ 3 | #define READ_BUTTONS_TM 1L // definitions in seconds 4 | #define READ_SOIL_TEMP_TM 2L 5 | #define READ_SOIL_HUM_TM 10L 6 | #define READ_AIR_DATA_TM 2L 7 | //#define DISPLAY_DATA_TM 5L 8 | 9 | /* OLED */ 10 | boolean turnOffOLED = 1; 11 | 12 | /* DHT22*/ 13 | #define DHTPIN D3 14 | #define DHTTYPE DHT22 15 | float airHum = 0; 16 | float airTemp = 0; 17 | 18 | /* Soil Moister */ 19 | #define soilMoisterPin A0 20 | #define soilMoisterVcc D8 21 | int soilMoister = 0; 22 | 23 | /* DS18B20 Temperature Sensor */ 24 | #define ONE_WIRE_BUS 14 // DS18B20 on NodeMCU pin D5 corresponds to GPIO 014 on Arduino 25 | float soilTemp; 26 | 27 | /* Relays */ 28 | #define PUMP_PIN D6 //PUMP (Red LED) 29 | #define LAMP_PIN D7 //LAMP (Green LED) 30 | boolean pumpStatus = 0; 31 | boolean lampStatus = 0; 32 | 33 | /* Buttons */ 34 | #define PUMP_ON_BUTTON D9 //push-button PUMP (Red) 35 | #define LAMP_ON_BUTTON D10 //push-button LAMP (Green) 36 | #define SENSORS_READ_BUTTON D4 //push-button SENSOR (yellow) 37 | 38 | 39 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V3_0/stationDefines.h: -------------------------------------------------------------------------------- 1 | 2 | /* Automatic Control Parameters Definition */ 3 | #define DRY_SOIL 66 4 | #define WET_SOIL 85 5 | #define COLD_TEMP 12 6 | #define HOT_TEMP 22 7 | #define TIME_PUMP_ON 15 8 | #define TIME_LAMP_ON 15 9 | 10 | /* TIMER */ 11 | #define READ_BUTTONS_TM 1L // definitions in seconds 12 | #define READ_SOIL_TEMP_TM 2L 13 | #define READ_SOIL_HUM_TM 10L 14 | #define READ_AIR_DATA_TM 2L 15 | #define SEND_UP_DATA_TM 10L 16 | #define AUTO_CTRL_TM 60L 17 | 18 | /* OLED */ 19 | boolean turnOffOLED = 1; 20 | #define SHOW_SET_UP 30 21 | 22 | /* DHT22*/ 23 | #define DHTPIN D3 24 | #define DHTTYPE DHT22 25 | float airHum = 0; 26 | float airTemp = 0; 27 | 28 | /* Soil Moister */ 29 | #define soilMoisterPin A0 30 | #define soilMoisterVcc D8 31 | int soilMoister = 0; 32 | 33 | /* DS18B20 Temperature Sensor */ 34 | #define ONE_WIRE_BUS 14 // DS18B20 on NodeMCU pin D5 corresponds to GPIO 014 on Arduino 35 | float soilTemp; 36 | 37 | /* Relays */ 38 | #define PUMP_PIN D6 //PUMP (Red LED) 39 | #define LAMP_PIN D7 //LAMP (Green LED) 40 | boolean pumpStatus = 0; 41 | boolean lampStatus = 0; 42 | 43 | /* Buttons */ 44 | #define PUMP_ON_BUTTON D9 //push-button PUMP (Red) 45 | #define LAMP_ON_BUTTON D10 //push-button LAMP (Green) 46 | #define SENSORS_READ_BUTTON D4 //push-button SENSOR (yellow) 47 | 48 | 49 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V4_0/stationDefines.h: -------------------------------------------------------------------------------- 1 | 2 | /* Automatic Control Parameters Definition */ 3 | #define DRY_SOIL 66 4 | #define WET_SOIL 85 5 | #define COLD_TEMP 12 6 | #define HOT_TEMP 22 7 | #define TIME_PUMP_ON 15 8 | #define TIME_LAMP_ON 15 9 | 10 | /* TIMER */ 11 | #define READ_BUTTONS_TM 1L // definitions in seconds 12 | #define READ_SOIL_TEMP_TM 2L 13 | #define READ_SOIL_HUM_TM 10L 14 | #define READ_AIR_DATA_TM 2L 15 | #define SEND_UP_DATA_TM 10L 16 | #define AUTO_CTRL_TM 60L 17 | 18 | /* OLED */ 19 | boolean turnOffOLED = 1; 20 | #define SHOW_SET_UP 30 21 | 22 | /* DHT22*/ 23 | #define DHTPIN D3 24 | #define DHTTYPE DHT22 25 | float airHum = 0; 26 | float airTemp = 0; 27 | 28 | /* Soil Moister */ 29 | #define soilMoisterPin A0 30 | #define soilMoisterVcc D8 31 | int soilMoister = 0; 32 | 33 | /* DS18B20 Temperature Sensor */ 34 | #define ONE_WIRE_BUS 14 // DS18B20 on NodeMCU pin D5 corresponds to GPIO 014 on Arduino 35 | float soilTemp; 36 | 37 | /* Relays */ 38 | #define PUMP_PIN D6 //PUMP (Red LED) 39 | #define LAMP_PIN D7 //LAMP (Green LED) 40 | boolean pumpStatus = 0; 41 | boolean lampStatus = 0; 42 | 43 | /* Buttons */ 44 | #define PUMP_ON_BUTTON D9 //push-button PUMP (Red) 45 | #define LAMP_ON_BUTTON D10 //push-button LAMP (Green) 46 | #define SENSORS_READ_BUTTON D4 //push-button SENSOR (yellow) 47 | 48 | 49 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Automatic_Ctrl_V2/stationDefines.h: -------------------------------------------------------------------------------- 1 | 2 | /* Automatic Control Parameters Definition */ 3 | #define DRY_SOIL 66 4 | #define WET_SOIL 85 5 | #define COLD_TEMP 12 6 | #define HOT_TEMP 22 7 | #define TIME_PUMP_ON 15 8 | #define TIME_LAMP_ON 15 9 | 10 | /* TIMER */ 11 | #define READ_BUTTONS_TM 1L // definitions in seconds 12 | #define READ_SOIL_TEMP_TM 2L 13 | #define READ_SOIL_HUM_TM 10L 14 | #define READ_AIR_DATA_TM 2L 15 | #define SEND_UP_DATA_TM 10L 16 | #define AUTO_CTRL_TM 60L 17 | 18 | /* OLED */ 19 | boolean turnOffOLED = 1; 20 | #define SHOW_SET_UP 30 21 | 22 | /* DHT22*/ 23 | #define DHTPIN D3 24 | #define DHTTYPE DHT22 25 | float airHum = 0; 26 | float airTemp = 0; 27 | 28 | /* Soil Moister */ 29 | #define soilMoisterPin A0 30 | #define soilMoisterVcc D8 31 | int soilMoister = 0; 32 | 33 | /* DS18B20 Temperature Sensor */ 34 | #define ONE_WIRE_BUS 14 // DS18B20 on NodeMCU pin D5 corresponds to GPIO 014 on Arduino 35 | float soilTemp; 36 | 37 | /* Relays */ 38 | #define PUMP_PIN D6 //PUMP (Red LED) 39 | #define LAMP_PIN D7 //LAMP (Green LED) 40 | boolean pumpStatus = 0; 41 | boolean lampStatus = 0; 42 | 43 | /* Buttons */ 44 | #define PUMP_ON_BUTTON D9 //push-button PUMP (Red) 45 | #define LAMP_ON_BUTTON D10 //push-button LAMP (Green) 46 | #define SENSORS_READ_BUTTON D4 //push-button SENSOR (yellow) 47 | 48 | 49 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Manual_Ctrl_V1/generalFunctions.ino: -------------------------------------------------------------------------------- 1 | 2 | /*************************************************** 3 | * Wait Button to be pressed a defined time in seconds 4 | ****************************************************/ 5 | void waitButtonPress (int waitTime) 6 | { 7 | long startTiming = millis(); 8 | while (debounce(SENSORS_READ_BUTTON)) 9 | { 10 | if ((millis()-startTiming) > (waitTime*1000)) break; 11 | } 12 | } 13 | 14 | /*************************************************** 15 | * Starting Timers 16 | ****************************************************/ 17 | void startTimers(void) 18 | { 19 | timer.setInterval(READ_BUTTONS_TM*1000, readLocalCmd); 20 | timer.setInterval(READ_SOIL_TEMP_TM*1000, getSoilTempData); 21 | timer.setInterval(READ_AIR_DATA_TM*1000, getDhtData); 22 | timer.setInterval(READ_SOIL_HUM_TM*1000, getSoilMoisterData); 23 | //timer.setInterval(DISPLAY_DATA_TM*1000, displayData); 24 | } 25 | 26 | /*************************************************** 27 | * Debouncing a key 28 | ****************************************************/ 29 | boolean debounce(int pin) 30 | { 31 | boolean state; 32 | boolean previousState; 33 | const int debounceDelay = 30; 34 | 35 | previousState = digitalRead(pin); 36 | for(int counter=0; counter< debounceDelay; counter++) 37 | { 38 | delay(1); 39 | state = digitalRead(pin); 40 | if(state != previousState) 41 | { 42 | counter = 0; 43 | previousState = state; 44 | } 45 | } 46 | return state; 47 | } 48 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Automatic_Ctrl_V2/generalFunctions.ino: -------------------------------------------------------------------------------- 1 | 2 | /*************************************************** 3 | * Wait Button to be pressed a defined time in seconds 4 | ****************************************************/ 5 | void waitButtonPress (int waitTime) 6 | { 7 | long startTiming = millis(); 8 | while (debounce(SENSORS_READ_BUTTON)) 9 | { 10 | if ((millis()-startTiming) > (waitTime*1000)) break; 11 | } 12 | } 13 | 14 | /*************************************************** 15 | * Starting Timers 16 | ****************************************************/ 17 | void startTimers(void) 18 | { 19 | timer.setInterval(READ_BUTTONS_TM*1000, readLocalCmd); 20 | timer.setInterval(READ_SOIL_TEMP_TM*1000, getSoilTempData); 21 | timer.setInterval(READ_AIR_DATA_TM*1000, getDhtData); 22 | timer.setInterval(READ_SOIL_HUM_TM*1000, getSoilMoisterData); 23 | timer.setInterval(AUTO_CTRL_TM*1000, autoControlPlantation); 24 | //timer.setInterval(DISPLAY_DATA_TM*1000, displayData); 25 | } 26 | 27 | /*************************************************** 28 | * Debouncing a key 29 | ****************************************************/ 30 | boolean debounce(int pin) 31 | { 32 | boolean state; 33 | boolean previousState; 34 | const int debounceDelay = 30; 35 | 36 | previousState = digitalRead(pin); 37 | for(int counter=0; counter< debounceDelay; counter++) 38 | { 39 | delay(1); 40 | state = digitalRead(pin); 41 | if(state != previousState) 42 | { 43 | counter = 0; 44 | previousState = state; 45 | } 46 | } 47 | return state; 48 | } 49 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V3_0/getSensors.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Get DHT data 3 | **************************************************/ 4 | void getDhtData(void) 5 | { 6 | float tempIni = airTemp; 7 | float humIni = airHum; 8 | airTemp = dht.readTemperature(); 9 | airHum = dht.readHumidity(); 10 | if (isnan(airHum) || isnan(airTemp)) // Check if any reads failed and exit early (to try again). 11 | { 12 | Serial.println("Failed to read from DHT sensor!"); 13 | airTemp = tempIni; 14 | airHum = humIni; 15 | return; 16 | } 17 | } 18 | 19 | /*************************************************** 20 | * Get Soil Moister Sensor data 21 | **************************************************/ 22 | void getSoilMoisterData(void) 23 | { 24 | soilMoister = 0; 25 | digitalWrite (soilMoisterVcc, HIGH); 26 | delay (500); 27 | int N = 3; 28 | for(int i = 0; i < N; i++) // read sensor "N" times and get the average 29 | { 30 | soilMoister += analogRead(soilMoisterPin); 31 | delay(150); 32 | } 33 | digitalWrite (soilMoisterVcc, LOW); 34 | soilMoister = soilMoister/N; 35 | soilMoister = map(soilMoister, 600, 0, 0, 100); //LM393 on 5V (+Vin) 36 | } 37 | 38 | /*************************************************** 39 | * Get SoilTemp sensor data 40 | **************************************************/ 41 | void getSoilTempData() 42 | { 43 | DS18B20.requestTemperatures(); 44 | soilTemp = DS18B20.getTempCByIndex(0); 45 | 46 | int newData = ((soilTemp + 0.05) * 10); //fix soilTemp value to 1 decimal place. 47 | soilTemp = (newData / 10.0); 48 | } 49 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V4_0/getSensors.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Get DHT data 3 | **************************************************/ 4 | void getDhtData(void) 5 | { 6 | float tempIni = airTemp; 7 | float humIni = airHum; 8 | airTemp = dht.readTemperature(); 9 | airHum = dht.readHumidity(); 10 | if (isnan(airHum) || isnan(airTemp)) // Check if any reads failed and exit early (to try again). 11 | { 12 | Serial.println("Failed to read from DHT sensor!"); 13 | airTemp = tempIni; 14 | airHum = humIni; 15 | return; 16 | } 17 | } 18 | 19 | /*************************************************** 20 | * Get Soil Moister Sensor data 21 | **************************************************/ 22 | void getSoilMoisterData(void) 23 | { 24 | soilMoister = 0; 25 | digitalWrite (soilMoisterVcc, HIGH); 26 | delay (500); 27 | int N = 3; 28 | for(int i = 0; i < N; i++) // read sensor "N" times and get the average 29 | { 30 | soilMoister += analogRead(soilMoisterPin); 31 | delay(150); 32 | } 33 | digitalWrite (soilMoisterVcc, LOW); 34 | soilMoister = soilMoister/N; 35 | soilMoister = map(soilMoister, 600, 0, 0, 100); //LM393 on 5V (+Vin) 36 | } 37 | 38 | /*************************************************** 39 | * Get SoilTemp sensor data 40 | **************************************************/ 41 | void getSoilTempData() 42 | { 43 | DS18B20.requestTemperatures(); 44 | soilTemp = DS18B20.getTempCByIndex(0); 45 | 46 | int newData = ((soilTemp + 0.05) * 10); //fix soilTemp value to 1 decimal place. 47 | soilTemp = (newData / 10.0); 48 | } 49 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Automatic_Ctrl_V2/getSensors.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Get DHT data 3 | **************************************************/ 4 | void getDhtData(void) 5 | { 6 | float tempIni = airTemp; 7 | float humIni = airHum; 8 | airTemp = dht.readTemperature(); 9 | airHum = dht.readHumidity(); 10 | if (isnan(airHum) || isnan(airTemp)) // Check if any reads failed and exit early (to try again). 11 | { 12 | Serial.println("Failed to read from DHT sensor!"); 13 | airTemp = tempIni; 14 | airHum = humIni; 15 | return; 16 | } 17 | } 18 | 19 | /*************************************************** 20 | * Get Soil Moister Sensor data 21 | **************************************************/ 22 | void getSoilMoisterData(void) 23 | { 24 | soilMoister = 0; 25 | digitalWrite (soilMoisterVcc, HIGH); 26 | delay (500); 27 | int N = 3; 28 | for(int i = 0; i < N; i++) // read sensor "N" times and get the average 29 | { 30 | soilMoister += analogRead(soilMoisterPin); 31 | delay(150); 32 | } 33 | digitalWrite (soilMoisterVcc, LOW); 34 | soilMoister = soilMoister/N; 35 | soilMoister = map(soilMoister, 600, 0, 0, 100); //LM393 on 5V (+Vin) 36 | } 37 | 38 | /*************************************************** 39 | * Get SoilTemp sensor data 40 | **************************************************/ 41 | void getSoilTempData() 42 | { 43 | DS18B20.requestTemperatures(); 44 | soilTemp = DS18B20.getTempCByIndex(0); 45 | 46 | int newData = ((soilTemp + 0.05) * 10); //fix soilTemp value to 1 decimal place. 47 | soilTemp = (newData / 10.0); 48 | } 49 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Manual_Ctrl_V1/getSensors.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Get DHT data 3 | **************************************************/ 4 | void getDhtData(void) 5 | { 6 | float tempIni = airTemp; 7 | float humIni = airHum; 8 | airTemp = dht.readTemperature(); 9 | airHum = dht.readHumidity(); 10 | if (isnan(airHum) || isnan(airTemp)) // Check if any reads failed and exit early (to try again). 11 | { 12 | Serial.println("Failed to read from DHT sensor!"); 13 | airTemp = tempIni; 14 | airHum = humIni; 15 | return; 16 | } 17 | } 18 | 19 | /*************************************************** 20 | * Get Soil Moister Sensor data 21 | **************************************************/ 22 | void getSoilMoisterData(void) 23 | { 24 | soilMoister = 0; 25 | digitalWrite (soilMoisterVcc, HIGH); 26 | delay (500); 27 | int N = 3; 28 | for(int i = 0; i < N; i++) // read sensor "N" times and get the average 29 | { 30 | soilMoister += analogRead(soilMoisterPin); 31 | delay(150); 32 | } 33 | digitalWrite (soilMoisterVcc, LOW); 34 | soilMoister = soilMoister/N; 35 | soilMoister = map(soilMoister, 600, 0, 0, 100); //LM393 on 5V (+Vin) 36 | } 37 | 38 | /*************************************************** 39 | * Get SoilTemp sensor data 40 | **************************************************/ 41 | void getSoilTempData() 42 | { 43 | DS18B20.requestTemperatures(); 44 | soilTemp = DS18B20.getTempCByIndex(0); 45 | 46 | int newData = ((soilTemp + 0.05) * 10); //fix soilTemp value to 1 decimal place. 47 | soilTemp = (newData / 10.0); 48 | } 49 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V3_0/generalFunctions.ino: -------------------------------------------------------------------------------- 1 | 2 | /*************************************************** 3 | * Wait Button to be pressed a defined time in seconds 4 | ****************************************************/ 5 | void waitButtonPress (int waitTime) 6 | { 7 | long startTiming = millis(); 8 | while (debounce(SENSORS_READ_BUTTON)) 9 | { 10 | if ((millis()-startTiming) > (waitTime*1000)) break; 11 | } 12 | } 13 | 14 | /*************************************************** 15 | * Starting Timers 16 | ****************************************************/ 17 | void startTimers(void) 18 | { 19 | timer.setInterval(READ_BUTTONS_TM*1000, readLocalCmd); 20 | timer.setInterval(READ_SOIL_TEMP_TM*1000, getSoilTempData); 21 | timer.setInterval(READ_AIR_DATA_TM*1000, getDhtData); 22 | timer.setInterval(READ_SOIL_HUM_TM*1000, getSoilMoisterData); 23 | timer.setInterval(SEND_UP_DATA_TM*1000, sendUptime); 24 | timer.setInterval(AUTO_CTRL_TM*1000, autoControlPlantation); 25 | //timer.setInterval(DISPLAY_DATA_TM*1000, displayData); 26 | } 27 | 28 | /*************************************************** 29 | * Debouncing a key 30 | ****************************************************/ 31 | boolean debounce(int pin) 32 | { 33 | boolean state; 34 | boolean previousState; 35 | const int debounceDelay = 30; 36 | 37 | previousState = digitalRead(pin); 38 | for(int counter=0; counter< debounceDelay; counter++) 39 | { 40 | delay(1); 41 | state = digitalRead(pin); 42 | if(state != previousState) 43 | { 44 | counter = 0; 45 | previousState = state; 46 | } 47 | } 48 | return state; 49 | } 50 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V4_0/generalFunctions.ino: -------------------------------------------------------------------------------- 1 | 2 | /*************************************************** 3 | * Wait Button to be pressed a defined time in seconds 4 | ****************************************************/ 5 | void waitButtonPress (int waitTime) 6 | { 7 | long startTiming = millis(); 8 | while (debounce(SENSORS_READ_BUTTON)) 9 | { 10 | if ((millis()-startTiming) > (waitTime*1000)) break; 11 | } 12 | } 13 | 14 | /*************************************************** 15 | * Starting Timers 16 | ****************************************************/ 17 | void startTimers(void) 18 | { 19 | timer.setInterval(READ_BUTTONS_TM*1000, readLocalCmd); 20 | timer.setInterval(READ_SOIL_TEMP_TM*1000, getSoilTempData); 21 | timer.setInterval(READ_AIR_DATA_TM*1000, getDhtData); 22 | timer.setInterval(READ_SOIL_HUM_TM*1000, getSoilMoisterData); 23 | timer.setInterval(SEND_UP_DATA_TM*1000, sendUptime); 24 | timer.setInterval(AUTO_CTRL_TM*1000, autoControlPlantation); 25 | //timer.setInterval(DISPLAY_DATA_TM*1000, displayData); 26 | } 27 | 28 | /*************************************************** 29 | * Debouncing a key 30 | ****************************************************/ 31 | boolean debounce(int pin) 32 | { 33 | boolean state; 34 | boolean previousState; 35 | const int debounceDelay = 30; 36 | 37 | previousState = digitalRead(pin); 38 | for(int counter=0; counter< debounceDelay; counter++) 39 | { 40 | delay(1); 41 | state = digitalRead(pin); 42 | if(state != previousState) 43 | { 44 | counter = 0; 45 | previousState = state; 46 | } 47 | } 48 | return state; 49 | } 50 | -------------------------------------------------------------------------------- /OneWire/examples/DS2408_Switch/DS2408_Switch.pde: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * DS2408 8-Channel Addressable Switch 5 | * 6 | * Writte by Glenn Trewitt, glenn at trewitt dot org 7 | * 8 | * Some notes about the DS2408: 9 | * - Unlike most input/output ports, the DS2408 doesn't have mode bits to 10 | * set whether the pins are input or output. If you issue a read command, 11 | * they're inputs. If you write to them, they're outputs. 12 | * - For reading from a switch, you should use 10K pull-up resisters. 13 | */ 14 | 15 | void PrintBytes(uint8_t* addr, uint8_t count, bool newline=0) { 16 | for (uint8_t i = 0; i < count; i++) { 17 | Serial.print(addr[i]>>4, HEX); 18 | Serial.print(addr[i]&0x0f, HEX); 19 | } 20 | if (newline) 21 | Serial.println(); 22 | } 23 | 24 | void ReadAndReport(OneWire* net, uint8_t* addr) { 25 | Serial.print(" Reading DS2408 "); 26 | PrintBytes(addr, 8); 27 | Serial.println(); 28 | 29 | uint8_t buf[13]; // Put everything in the buffer so we can compute CRC easily. 30 | buf[0] = 0xF0; // Read PIO Registers 31 | buf[1] = 0x88; // LSB address 32 | buf[2] = 0x00; // MSB address 33 | net->write_bytes(buf, 3); 34 | net->read_bytes(buf+3, 10); // 3 cmd bytes, 6 data bytes, 2 0xFF, 2 CRC16 35 | net->reset(); 36 | 37 | if (!OneWire::check_crc16(buf, 11, &buf[11])) { 38 | Serial.print("CRC failure in DS2408 at "); 39 | PrintBytes(addr, 8, true); 40 | return; 41 | } 42 | Serial.print(" DS2408 data = "); 43 | // First 3 bytes contain command, register address. 44 | Serial.println(buf[3], BIN); 45 | } 46 | 47 | OneWire net(2); // on pin 2 48 | 49 | void setup(void) { 50 | Serial.begin(9600); 51 | } 52 | 53 | void loop(void) { 54 | byte i; 55 | byte present = 0; 56 | byte addr[8]; 57 | 58 | if (!net.search(addr)) { 59 | Serial.print("No more addresses.\n"); 60 | net.reset_search(); 61 | delay(1000); 62 | return; 63 | } 64 | 65 | if (OneWire::crc8(addr, 7) != addr[7]) { 66 | Serial.print("CRC is not valid!\n"); 67 | return; 68 | } 69 | 70 | if (addr[0] != 0x29) { 71 | PrintBytes(addr, 8); 72 | Serial.print(" is not a DS2408.\n"); 73 | return; 74 | } 75 | 76 | ReadAndReport(&net, addr); 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ArduFarmBot-2 2 | Automatic Gardening System with NodeMCU and Blynk 3 |

This complete tutorial can be found at: https://www.instructables.com/id/Automatic-Gardening-System-With-NodeMCU-and-Blynk-/

4 |

Some time ago, we developed a similar project: "ArduFarmBot: Controlling a Tomato Home Farm using Arduino and IoT". On this new version, the ArduFarmBot 2, the main specification of the original project will be kept. We will develop a fully automated Gardening System based on NodeMCU ESP8266 and an IoT app, the BLYNK.

Basically, information from a plantation will be captured, temperature and humidity, both from air and soil. Based on those data, the ArduFarmBot 2 will decide the right amount (and when) the plantation should receive heat and water. Also the project should allow manual intervention of an operator in order to control a water pump and an electric lamp to generate heat for the plantation. The manual intervention must be both, local and remote via Internet.

In short, the system should receive as input:

    5 |
  • Sensors: 6 |
      7 |
    • Air Temperature 8 |
    • Air Relative Humidity 9 |
    • Soil Temperature 10 |
    • Soil Moisture (humidity)
    11 |
  • Buttons: 12 |
      13 |
    • Pump ON/OFF 14 |
    • Lamp ON/OFF

The system should provide as an output:

    15 |
  • Actuators: 16 |
      17 |
    • Relay for Pump control 18 |
    • Relay for Lamp control
    19 |
  • Messages 20 |
      21 |
    • Automatic messages must be sent on main events as: 22 |
        23 |
      • Pump ON 24 |
      • Lamo On 25 |
      • System Off-line
    26 |
  • Data Display 27 |
      28 |
    • All analog and digital data should be available for instant evaluation
    29 |
  • Data Storage 30 |
      31 |
    • 32 |

      Historic data should be storage remotely

The block diagram shows the main components of the project.

33 |

34 | ArduFarmBot2 Block Diagram 35 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Manual_Ctrl_V1/oledDisplay.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Start OLED 3 | **************************************************/ 4 | void oledStart(void) 5 | { 6 | Wire.begin(); 7 | oled.init(); // Initialze SSD1306 OLED display 8 | clearOledDisplay(); 9 | //oled.setFont(font5x7); // Set font type (default 8x8) 10 | oled.clearDisplay(); // Clear screen 11 | oled.setTextXY(0,0); 12 | oled.putString(" ArduFarmBot 2 "); 13 | oled.setTextXY(1,0); 14 | oled.putString(String(SW_VERSION)); 15 | oled.setTextXY(7,0); 16 | oled.putString("Sensor Key ==>>"); 17 | } 18 | 19 | /*************************************************** 20 | * Display data at Serial Monitora & OLED Display 21 | **************************************************/ 22 | void displayData(void) 23 | { 24 | oled.setTextXY(3,0); oled.putString("AirTmp [C] "); 25 | oled.setTextXY(3,11); oled.putString(" "); 26 | oled.setTextXY(3,11); oled.putString(String(airTemp)); 27 | 28 | oled.setTextXY(4,0); oled.putString("AirHum [%] "); 29 | oled.setTextXY(4,11); oled.putString(" "); 30 | oled.setTextXY(4,11); oled.putString(String(airHum)); 31 | 32 | oled.setTextXY(5,0); oled.putString("SoilTmp[C] "); 33 | oled.setTextXY(5,11); oled.putString(" "); 34 | oled.setTextXY(5,11); oled.putString(String(soilTemp)); 35 | 36 | oled.setTextXY(6,0); oled.putString("SoilHum[%] "); 37 | oled.setTextXY(6,11); oled.putString(" "); 38 | oled.setTextXY(6,11); oled.putString(String(soilMoister)); 39 | 40 | oled.setTextXY(7,0); oled.putString("PUMP: "); 41 | oled.setTextXY(7,6); oled.putString(String(pumpStatus)); 42 | 43 | oled.setTextXY(7,7); oled.putString(" LAMP: "); 44 | oled.setTextXY(7,15); oled.putString(String(lampStatus)); 45 | } 46 | 47 | /*************************************************** 48 | * Clear OLED Display 49 | **************************************************/ 50 | void clearOledDisplay() 51 | { 52 | oled.setFont(font8x8); 53 | oled.setTextXY(0,0); oled.putString(" "); 54 | oled.setTextXY(1,0); oled.putString(" "); 55 | oled.setTextXY(2,0); oled.putString(" "); 56 | oled.setTextXY(3,0); oled.putString(" "); 57 | oled.setTextXY(4,0); oled.putString(" "); 58 | oled.setTextXY(5,0); oled.putString(" "); 59 | oled.setTextXY(6,0); oled.putString(" "); 60 | oled.setTextXY(7,0); oled.putString(" "); 61 | oled.setTextXY(0,0); oled.putString(" "); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V3_0/oledDisplay.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Start OLED 3 | **************************************************/ 4 | void oledStart(void) 5 | { 6 | Wire.begin(); 7 | oled.init(); // Initialze SSD1306 OLED display 8 | clearOledDisplay(); 9 | //oled.setFont(font5x7); // Set font type (default 8x8) 10 | oled.clearDisplay(); // Clear screen 11 | 12 | oled.setTextXY(0,0); oled.putString(" ArduFarmBot 2 "); 13 | oled.setTextXY(1,0); oled.putString(String(SW_VERSION)); 14 | 15 | oled.setTextXY(2,0); oled.putString("AUTO_CTRL_TM"); 16 | oled.setTextXY(2,13); oled.putString(String(AUTO_CTRL_TM)); 17 | oled.setTextXY(3,0); oled.putString("DRY_SOIL"); 18 | oled.setTextXY(3,13); oled.putString(String(DRY_SOIL)); 19 | oled.setTextXY(4,0); oled.putString("COLD_TEMP"); 20 | oled.setTextXY(4,13); oled.putString(String(COLD_TEMP)); 21 | oled.setTextXY(5,0); oled.putString("TIME_PUMP_ON"); 22 | oled.setTextXY(5,13); oled.putString(String(TIME_PUMP_ON)); 23 | oled.setTextXY(6,0); oled.putString("TIME_LAMP_ON"); 24 | oled.setTextXY(6,13); oled.putString(String(TIME_LAMP_ON)); 25 | oled.setTextXY(7,0); oled.putString("Sensor Key ==>>"); 26 | } 27 | 28 | /*************************************************** 29 | * Display data at Serial Monitora & OLED Display 30 | **************************************************/ 31 | void displayData(void) 32 | { 33 | String pumpStatusStr; 34 | String lampStatusStr; 35 | if (pumpStatus == 1) pumpStatusStr = "on "; 36 | if (pumpStatus == 0) pumpStatusStr = "off"; 37 | if (lampStatus == 1) lampStatusStr = "on "; 38 | if (lampStatus == 0) lampStatusStr = "off"; 39 | 40 | oled.setTextXY(2,0); oled.putString(" "); 41 | 42 | oled.setTextXY(3,0); oled.putString("AirTmp [C] "); 43 | oled.setTextXY(3,11); oled.putString(" "); 44 | oled.setTextXY(3,11); oled.putString(String(airTemp)); 45 | 46 | oled.setTextXY(4,0); oled.putString("AirHum [%] "); 47 | oled.setTextXY(4,11); oled.putString(" "); 48 | oled.setTextXY(4,11); oled.putString(String(airHum)); 49 | 50 | oled.setTextXY(5,0); oled.putString("SoilTmp[C] "); 51 | oled.setTextXY(5,11); oled.putString(" "); 52 | oled.setTextXY(5,11); oled.putString(String(soilTemp)); 53 | 54 | oled.setTextXY(6,0); oled.putString("SoilHum[%] "); 55 | oled.setTextXY(6,11); oled.putString(" "); 56 | oled.setTextXY(6,11); oled.putString(String(soilMoister)); 57 | 58 | oled.setTextXY(7,0); oled.putString("PMP "); 59 | oled.setTextXY(7,4); oled.putString(pumpStatusStr); 60 | 61 | oled.setTextXY(7,7); oled.putString(" LMP "); 62 | oled.setTextXY(7,13); oled.putString(lampStatusStr); 63 | } 64 | 65 | /*************************************************** 66 | * Clear OLED Display 67 | **************************************************/ 68 | void clearOledDisplay() 69 | { 70 | oled.setFont(font8x8); 71 | oled.setTextXY(0,0); oled.putString(" "); 72 | oled.setTextXY(1,0); oled.putString(" "); 73 | oled.setTextXY(2,0); oled.putString(" "); 74 | oled.setTextXY(3,0); oled.putString(" "); 75 | oled.setTextXY(4,0); oled.putString(" "); 76 | oled.setTextXY(5,0); oled.putString(" "); 77 | oled.setTextXY(6,0); oled.putString(" "); 78 | oled.setTextXY(7,0); oled.putString(" "); 79 | oled.setTextXY(0,0); oled.putString(" "); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V4_0/oledDisplay.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Start OLED 3 | **************************************************/ 4 | void oledStart(void) 5 | { 6 | Wire.begin(); 7 | oled.init(); // Initialze SSD1306 OLED display 8 | clearOledDisplay(); 9 | //oled.setFont(font5x7); // Set font type (default 8x8) 10 | oled.clearDisplay(); // Clear screen 11 | 12 | oled.setTextXY(0,0); oled.putString(" ArduFarmBot 2 "); 13 | oled.setTextXY(1,0); oled.putString(String(SW_VERSION)); 14 | 15 | oled.setTextXY(2,0); oled.putString("AUTO_CTRL_TM"); 16 | oled.setTextXY(2,13); oled.putString(String(AUTO_CTRL_TM)); 17 | oled.setTextXY(3,0); oled.putString("DRY_SOIL"); 18 | oled.setTextXY(3,13); oled.putString(String(DRY_SOIL)); 19 | oled.setTextXY(4,0); oled.putString("COLD_TEMP"); 20 | oled.setTextXY(4,13); oled.putString(String(COLD_TEMP)); 21 | oled.setTextXY(5,0); oled.putString("TIME_PUMP_ON"); 22 | oled.setTextXY(5,13); oled.putString(String(TIME_PUMP_ON)); 23 | oled.setTextXY(6,0); oled.putString("TIME_LAMP_ON"); 24 | oled.setTextXY(6,13); oled.putString(String(TIME_LAMP_ON)); 25 | oled.setTextXY(7,0); oled.putString("Sensor Key ==>>"); 26 | } 27 | 28 | /*************************************************** 29 | * Display data at Serial Monitora & OLED Display 30 | **************************************************/ 31 | void displayData(void) 32 | { 33 | String pumpStatusStr; 34 | String lampStatusStr; 35 | if (pumpStatus == 1) pumpStatusStr = "on "; 36 | if (pumpStatus == 0) pumpStatusStr = "off"; 37 | if (lampStatus == 1) lampStatusStr = "on "; 38 | if (lampStatus == 0) lampStatusStr = "off"; 39 | 40 | oled.setTextXY(2,0); oled.putString(" "); 41 | 42 | oled.setTextXY(3,0); oled.putString("AirTmp [C] "); 43 | oled.setTextXY(3,11); oled.putString(" "); 44 | oled.setTextXY(3,11); oled.putString(String(airTemp)); 45 | 46 | oled.setTextXY(4,0); oled.putString("AirHum [%] "); 47 | oled.setTextXY(4,11); oled.putString(" "); 48 | oled.setTextXY(4,11); oled.putString(String(airHum)); 49 | 50 | oled.setTextXY(5,0); oled.putString("SoilTmp[C] "); 51 | oled.setTextXY(5,11); oled.putString(" "); 52 | oled.setTextXY(5,11); oled.putString(String(soilTemp)); 53 | 54 | oled.setTextXY(6,0); oled.putString("SoilHum[%] "); 55 | oled.setTextXY(6,11); oled.putString(" "); 56 | oled.setTextXY(6,11); oled.putString(String(soilMoister)); 57 | 58 | oled.setTextXY(7,0); oled.putString("PMP "); 59 | oled.setTextXY(7,4); oled.putString(pumpStatusStr); 60 | 61 | oled.setTextXY(7,7); oled.putString(" LMP "); 62 | oled.setTextXY(7,13); oled.putString(lampStatusStr); 63 | } 64 | 65 | /*************************************************** 66 | * Clear OLED Display 67 | **************************************************/ 68 | void clearOledDisplay() 69 | { 70 | oled.setFont(font8x8); 71 | oled.setTextXY(0,0); oled.putString(" "); 72 | oled.setTextXY(1,0); oled.putString(" "); 73 | oled.setTextXY(2,0); oled.putString(" "); 74 | oled.setTextXY(3,0); oled.putString(" "); 75 | oled.setTextXY(4,0); oled.putString(" "); 76 | oled.setTextXY(5,0); oled.putString(" "); 77 | oled.setTextXY(6,0); oled.putString(" "); 78 | oled.setTextXY(7,0); oled.putString(" "); 79 | oled.setTextXY(0,0); oled.putString(" "); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Automatic_Ctrl_V2/oledDisplay.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * Start OLED 3 | **************************************************/ 4 | void oledStart(void) 5 | { 6 | Wire.begin(); 7 | oled.init(); // Initialze SSD1306 OLED display 8 | clearOledDisplay(); 9 | //oled.setFont(font5x7); // Set font type (default 8x8) 10 | oled.clearDisplay(); // Clear screen 11 | 12 | oled.setTextXY(0,0); oled.putString(" ArduFarmBot 2 "); 13 | oled.setTextXY(1,0); oled.putString(String(SW_VERSION)); 14 | 15 | oled.setTextXY(2,0); oled.putString("AUTO_CTRL_TM"); 16 | oled.setTextXY(2,13); oled.putString(String(AUTO_CTRL_TM)); 17 | oled.setTextXY(3,0); oled.putString("DRY_SOIL"); 18 | oled.setTextXY(3,13); oled.putString(String(DRY_SOIL)); 19 | oled.setTextXY(4,0); oled.putString("COLD_TEMP"); 20 | oled.setTextXY(4,13); oled.putString(String(COLD_TEMP)); 21 | oled.setTextXY(5,0); oled.putString("TIME_PUMP_ON"); 22 | oled.setTextXY(5,13); oled.putString(String(TIME_PUMP_ON)); 23 | oled.setTextXY(6,0); oled.putString("TIME_LAMP_ON"); 24 | oled.setTextXY(6,13); oled.putString(String(TIME_LAMP_ON)); 25 | oled.setTextXY(7,0); oled.putString("Sensor Key ==>>"); 26 | } 27 | 28 | /*************************************************** 29 | * Display data at Serial Monitora & OLED Display 30 | **************************************************/ 31 | void displayData(void) 32 | { 33 | String pumpStatusStr; 34 | String lampStatusStr; 35 | if (pumpStatus == 1) pumpStatusStr = "on "; 36 | if (pumpStatus == 0) pumpStatusStr = "off"; 37 | if (lampStatus == 1) lampStatusStr = "on "; 38 | if (lampStatus == 0) lampStatusStr = "off"; 39 | 40 | oled.setTextXY(2,0); oled.putString(" "); 41 | 42 | oled.setTextXY(3,0); oled.putString("AirTmp [C] "); 43 | oled.setTextXY(3,11); oled.putString(" "); 44 | oled.setTextXY(3,11); oled.putString(String(airTemp)); 45 | 46 | oled.setTextXY(4,0); oled.putString("AirHum [%] "); 47 | oled.setTextXY(4,11); oled.putString(" "); 48 | oled.setTextXY(4,11); oled.putString(String(airHum)); 49 | 50 | oled.setTextXY(5,0); oled.putString("SoilTmp[C] "); 51 | oled.setTextXY(5,11); oled.putString(" "); 52 | oled.setTextXY(5,11); oled.putString(String(soilTemp)); 53 | 54 | oled.setTextXY(6,0); oled.putString("SoilHum[%] "); 55 | oled.setTextXY(6,11); oled.putString(" "); 56 | oled.setTextXY(6,11); oled.putString(String(soilMoister)); 57 | 58 | oled.setTextXY(7,0); oled.putString("PMP "); 59 | oled.setTextXY(7,4); oled.putString(pumpStatusStr); 60 | 61 | oled.setTextXY(7,7); oled.putString(" LMP "); 62 | oled.setTextXY(7,13); oled.putString(lampStatusStr); 63 | } 64 | 65 | /*************************************************** 66 | * Clear OLED Display 67 | **************************************************/ 68 | void clearOledDisplay() 69 | { 70 | oled.setFont(font8x8); 71 | oled.setTextXY(0,0); oled.putString(" "); 72 | oled.setTextXY(1,0); oled.putString(" "); 73 | oled.setTextXY(2,0); oled.putString(" "); 74 | oled.setTextXY(3,0); oled.putString(" "); 75 | oled.setTextXY(4,0); oled.putString(" "); 76 | oled.setTextXY(5,0); oled.putString(" "); 77 | oled.setTextXY(6,0); oled.putString(" "); 78 | oled.setTextXY(7,0); oled.putString(" "); 79 | oled.setTextXY(0,0); oled.putString(" "); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /DHT22_Test_with_Oled/DHT22_Test_with_Oled.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************************** 2 | * IoT DHT Temp/Hum Station using NodeMCU ESP-12 Develop Kit V1.0 3 | * DHT connected to NodeMCU pin D3 4 | * DHT Data on local OLED Display 5 | * 6 | * Developed by MJRovai 12 October 2017 7 | ********************************************************************************************************************************/ 8 | 9 | /* OLED */ 10 | #include // library for OLED: SCL ==> D1; SDA ==> D2 11 | #include 12 | #include 13 | 14 | /* DHT22*/ 15 | #include "DHT.h" 16 | #define DHTPIN D3 17 | #define DHTTYPE DHT22 18 | DHT dht(DHTPIN, DHTTYPE); 19 | float hum = 0; 20 | float temp = 0; 21 | 22 | void setup() 23 | { 24 | Serial.begin(115200); 25 | delay(10); 26 | dht.begin(); 27 | oledStart(); 28 | } 29 | 30 | void loop() 31 | { 32 | getDhtData(); 33 | displayData(); 34 | delay(2000); // delay for getting DHT22 data 35 | } 36 | 37 | /*************************************************** 38 | * Start OLED 39 | **************************************************/ 40 | void oledStart(void) 41 | { 42 | Wire.begin(); 43 | oled.init(); // Initialze SSD1306 OLED display 44 | clearOledDisplay(); 45 | oled.clearDisplay(); // Clear screen 46 | oled.setTextXY(0,0); 47 | oled.putString(" MJRoBot.org"); 48 | } 49 | 50 | /*************************************************** 51 | * Get DHT data 52 | **************************************************/ 53 | void getDhtData(void) 54 | { 55 | float tempIni = temp; 56 | float humIni = hum; 57 | temp = dht.readTemperature(); 58 | hum = dht.readHumidity(); 59 | if (isnan(hum) || isnan(temp)) // Check if any reads failed and exit early (to try again). 60 | { 61 | Serial.println("Failed to read from DHT sensor!"); 62 | temp = tempIni; 63 | hum = humIni; 64 | return; 65 | } 66 | } 67 | 68 | /*************************************************** 69 | * Display data at Serial Monitora & OLED Display 70 | **************************************************/ 71 | void displayData(void) 72 | { 73 | Serial.print(" Temperature: "); 74 | Serial.print(temp); 75 | Serial.print("oC Humidity: "); 76 | Serial.print(hum); 77 | Serial.println("%"); 78 | 79 | oled.setTextXY(3,0); // Set cursor position, start of line 2 80 | oled.putString("TEMP: " + String(temp) + " oC"); 81 | oled.setTextXY(5,0); // Set cursor position, start of line 2 82 | oled.putString("HUM: " + String(hum) + " %"); 83 | } 84 | 85 | /*************************************************** 86 | * Clear OLED Display 87 | **************************************************/ 88 | void clearOledDisplay() 89 | { 90 | oled.setFont(font8x8); 91 | oled.setTextXY(0,0); oled.putString(" "); 92 | oled.setTextXY(1,0); oled.putString(" "); 93 | oled.setTextXY(2,0); oled.putString(" "); 94 | oled.setTextXY(3,0); oled.putString(" "); 95 | oled.setTextXY(4,0); oled.putString(" "); 96 | oled.setTextXY(5,0); oled.putString(" "); 97 | oled.setTextXY(6,0); oled.putString(" "); 98 | oled.setTextXY(7,0); oled.putString(" "); 99 | oled.setTextXY(0,0); oled.putString(" "); 100 | } 101 | 102 | -------------------------------------------------------------------------------- /ArduFarmBot2_PartialTest/ArduFarmBot2_PartialTest.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************************** 2 | * IoT DHT Temp/Hum Station using NodeMCU ESP-12 Develop Kit V1.0 3 | * DHT connected to NodeMCU pin D3 4 | * DHT Data on local OLED Display 5 | * 6 | * Developed by MJRovai 12 October 2017 7 | ********************************************************************************************************************************/ 8 | 9 | /* OLED */ 10 | #include // library for OLED: SCL ==> D1; SDA ==> D2 11 | #include 12 | #include 13 | 14 | /* DHT22*/ 15 | #include "DHT.h" 16 | #define DHTPIN D3 17 | #define DHTTYPE DHT22 18 | DHT dht(DHTPIN, DHTTYPE); 19 | float hum = 0; 20 | float temp = 0; 21 | 22 | void setup() 23 | { 24 | Serial.begin(115200); 25 | delay(10); 26 | dht.begin(); 27 | oledStart(); 28 | } 29 | 30 | void loop() 31 | { 32 | getDhtData(); 33 | displayData(); 34 | delay(2000); // delay for getting DHT22 data 35 | } 36 | 37 | /*************************************************** 38 | * Start OLED 39 | **************************************************/ 40 | void oledStart(void) 41 | { 42 | Wire.begin(); 43 | oled.init(); // Initialze SSD1306 OLED display 44 | clearOledDisplay(); 45 | oled.clearDisplay(); // Clear screen 46 | oled.setTextXY(0,0); 47 | oled.putString(" MJRoBot.org"); 48 | } 49 | 50 | /*************************************************** 51 | * Get DHT data 52 | **************************************************/ 53 | void getDhtData(void) 54 | { 55 | float tempIni = temp; 56 | float humIni = hum; 57 | temp = dht.readTemperature(); 58 | hum = dht.readHumidity(); 59 | if (isnan(hum) || isnan(temp)) // Check if any reads failed and exit early (to try again). 60 | { 61 | Serial.println("Failed to read from DHT sensor!"); 62 | temp = tempIni; 63 | hum = humIni; 64 | return; 65 | } 66 | } 67 | 68 | /*************************************************** 69 | * Display data at Serial Monitora & OLED Display 70 | **************************************************/ 71 | void displayData(void) 72 | { 73 | Serial.print(" Temperature: "); 74 | Serial.print(temp); 75 | Serial.print("oC Humidity: "); 76 | Serial.print(hum); 77 | Serial.println("%"); 78 | 79 | oled.setTextXY(3,0); // Set cursor position, start of line 2 80 | oled.putString("TEMP: " + String(temp) + " oC"); 81 | oled.setTextXY(5,0); // Set cursor position, start of line 2 82 | oled.putString("HUM: " + String(hum) + " %"); 83 | } 84 | 85 | /*************************************************** 86 | * Clear OLED Display 87 | **************************************************/ 88 | void clearOledDisplay() 89 | { 90 | oled.setFont(font8x8); 91 | oled.setTextXY(0,0); oled.putString(" "); 92 | oled.setTextXY(1,0); oled.putString(" "); 93 | oled.setTextXY(2,0); oled.putString(" "); 94 | oled.setTextXY(3,0); oled.putString(" "); 95 | oled.setTextXY(4,0); oled.putString(" "); 96 | oled.setTextXY(5,0); oled.putString(" "); 97 | oled.setTextXY(6,0); oled.putString(" "); 98 | oled.setTextXY(7,0); oled.putString(" "); 99 | oled.setTextXY(0,0); oled.putString(" "); 100 | } 101 | 102 | -------------------------------------------------------------------------------- /OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // OneWire DS18S20, DS18B20, DS1822 Temperature Example 4 | // 5 | // http://www.pjrc.com/teensy/td_libs_OneWire.html 6 | // 7 | // The DallasTemperature library can do all this work for you! 8 | // http://milesburton.com/Dallas_Temperature_Control_Library 9 | 10 | OneWire ds(2); // on pin 2 (a 4.7K resistor is necessary) 11 | 12 | void setup(void) { 13 | Serial.begin(9600); 14 | } 15 | 16 | void loop(void) { 17 | byte i; 18 | byte present = 0; 19 | byte type_s; 20 | byte data[12]; 21 | byte addr[8]; 22 | float celsius, fahrenheit; 23 | 24 | if ( !ds.search(addr)) { 25 | Serial.println("No more addresses."); 26 | Serial.println(); 27 | ds.reset_search(); 28 | delay(250); 29 | return; 30 | } 31 | 32 | Serial.print("ROM ="); 33 | for( i = 0; i < 8; i++) { 34 | Serial.write(' '); 35 | Serial.print(addr[i], HEX); 36 | } 37 | 38 | if (OneWire::crc8(addr, 7) != addr[7]) { 39 | Serial.println("CRC is not valid!"); 40 | return; 41 | } 42 | Serial.println(); 43 | 44 | // the first ROM byte indicates which chip 45 | switch (addr[0]) { 46 | case 0x10: 47 | Serial.println(" Chip = DS18S20"); // or old DS1820 48 | type_s = 1; 49 | break; 50 | case 0x28: 51 | Serial.println(" Chip = DS18B20"); 52 | type_s = 0; 53 | break; 54 | case 0x22: 55 | Serial.println(" Chip = DS1822"); 56 | type_s = 0; 57 | break; 58 | default: 59 | Serial.println("Device is not a DS18x20 family device."); 60 | return; 61 | } 62 | 63 | ds.reset(); 64 | ds.select(addr); 65 | ds.write(0x44, 1); // start conversion, with parasite power on at the end 66 | 67 | delay(1000); // maybe 750ms is enough, maybe not 68 | // we might do a ds.depower() here, but the reset will take care of it. 69 | 70 | present = ds.reset(); 71 | ds.select(addr); 72 | ds.write(0xBE); // Read Scratchpad 73 | 74 | Serial.print(" Data = "); 75 | Serial.print(present, HEX); 76 | Serial.print(" "); 77 | for ( i = 0; i < 9; i++) { // we need 9 bytes 78 | data[i] = ds.read(); 79 | Serial.print(data[i], HEX); 80 | Serial.print(" "); 81 | } 82 | Serial.print(" CRC="); 83 | Serial.print(OneWire::crc8(data, 8), HEX); 84 | Serial.println(); 85 | 86 | // Convert the data to actual temperature 87 | // because the result is a 16 bit signed integer, it should 88 | // be stored to an "int16_t" type, which is always 16 bits 89 | // even when compiled on a 32 bit processor. 90 | int16_t raw = (data[1] << 8) | data[0]; 91 | if (type_s) { 92 | raw = raw << 3; // 9 bit resolution default 93 | if (data[7] == 0x10) { 94 | // "count remain" gives full 12 bit resolution 95 | raw = (raw & 0xFFF0) + 12 - data[6]; 96 | } 97 | } else { 98 | byte cfg = (data[4] & 0x60); 99 | // at lower res, the low bits are undefined, so let's zero them 100 | if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms 101 | else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms 102 | else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms 103 | //// default is 12 bit resolution, 750 ms conversion time 104 | } 105 | celsius = (float)raw / 16.0; 106 | fahrenheit = celsius * 1.8 + 32.0; 107 | Serial.print(" Temperature = "); 108 | Serial.print(celsius); 109 | Serial.print(" Celsius, "); 110 | Serial.print(fahrenheit); 111 | Serial.println(" Fahrenheit"); 112 | } 113 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Manual_Ctrl_V1/ArduFarmBot2_Local_Manual_Ctrl_V1.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************************** 2 | * ArduFarmBot using NodeMCU ESP-12 Develop Kit V1.0 3 | * DHT connected to NodeMCU pin D3 (Ambient Temperature and Relative Humidity) 4 | * Soil Moister Sensor connected to A0 5 | * Sensor Data on local OLED Display 6 | * Local Command via buttons 7 | * OLED Display is off as default. Press Sensor Button to update and display data 8 | * Introduced the function "waitButtonPress (int waitTime)", to break initial loop 9 | * 10 | * Version 1.0 - Manual and Local Control - Developed by MJRovai 15 Feb 2017 11 | ********************************************************************************************************************************/ 12 | #define SW_VERSION " SW Ver. 1,0" // SW version will appears at innitial LCD Display 13 | #include "stationDefines.h" // Project definitions 14 | 15 | /* ESP */ 16 | #include 17 | 18 | /* TIMER */ 19 | #include 20 | SimpleTimer timer; 21 | 22 | /* OLED */ 23 | #include // library for OLED: SCL ==> D1; SDA ==> D2 24 | #include 25 | #include 26 | 27 | /* DHT22*/ 28 | #include "DHT.h" 29 | DHT dht(DHTPIN, DHTTYPE); 30 | 31 | /* DS18B20 Temperature Sensor */ 32 | #include 33 | #include 34 | OneWire oneWire(ONE_WIRE_BUS); 35 | DallasTemperature DS18B20(&oneWire); 36 | 37 | void setup() 38 | { 39 | Serial.begin(115200); 40 | delay(10); 41 | Serial.println("ArduFarmBot 2"); 42 | Serial.println(".... Starting Setup"); 43 | Serial.println(" "); 44 | 45 | pinMode(PUMP_PIN, OUTPUT); 46 | pinMode(LAMP_PIN, OUTPUT); 47 | pinMode(PUMP_ON_BUTTON, INPUT_PULLUP); 48 | pinMode(LAMP_ON_BUTTON, INPUT_PULLUP); 49 | pinMode(SENSORS_READ_BUTTON, INPUT_PULLUP); 50 | pinMode(soilMoisterVcc, OUTPUT); 51 | 52 | oledStart(); 53 | dht.begin(); 54 | DS18B20.begin(); 55 | 56 | digitalWrite(PUMP_PIN, LOW); 57 | digitalWrite(LAMP_PIN, LOW); 58 | digitalWrite (soilMoisterVcc, LOW); 59 | 60 | waitButtonPress (10); // Wait 10 seconds for Sensor Button to be pressed 61 | oled.clearDisplay(); 62 | startTimers(); 63 | } 64 | 65 | void loop() 66 | { 67 | timer.run(); // Initiates SimpleTimer 68 | } 69 | 70 | /**************************************************************** 71 | * Read local commands (Pump and Lamp buttons are normally "HIGH"): 72 | ****************************************************************/ 73 | void readLocalCmd() 74 | { 75 | boolean digiValue = debounce(PUMP_ON_BUTTON); 76 | if (!digiValue) 77 | { 78 | pumpStatus = !pumpStatus; 79 | aplyCmd(); 80 | } 81 | 82 | digiValue = debounce(LAMP_ON_BUTTON); 83 | if (!digiValue) 84 | { 85 | lampStatus = !lampStatus; 86 | aplyCmd(); 87 | } 88 | 89 | digiValue = debounce(SENSORS_READ_BUTTON); 90 | if (!digiValue) 91 | { 92 | turnOffOLED = !turnOffOLED; 93 | if (!turnOffOLED) 94 | { 95 | oled.setTextXY(0,0); oled.putString("UPDATING SENSORS"); 96 | getDhtData(); 97 | getSoilMoisterData(); 98 | getSoilTempData(); 99 | oledStart(); 100 | displayData(); 101 | }else oled.clearDisplay(); 102 | } 103 | } 104 | 105 | /*************************************************** 106 | * Receive Commands and act on actuators 107 | ****************************************************/ 108 | void aplyCmd() 109 | { 110 | if (pumpStatus == 1) 111 | { 112 | digitalWrite(PUMP_PIN, HIGH); 113 | if (!turnOffOLED) displayData(); 114 | } 115 | else 116 | { 117 | digitalWrite(PUMP_PIN, LOW); 118 | if (!turnOffOLED) displayData(); 119 | } 120 | 121 | if (lampStatus == 1) 122 | { 123 | digitalWrite(LAMP_PIN, HIGH); 124 | if (!turnOffOLED) displayData(); 125 | } 126 | else 127 | { 128 | digitalWrite(LAMP_PIN, LOW); 129 | if (!turnOffOLED) displayData(); 130 | } 131 | } 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /OneWire/examples/DS250x_PROM/DS250x_PROM.pde: -------------------------------------------------------------------------------- 1 | /* 2 | DS250x add-only programmable memory reader w/SKIP ROM. 3 | 4 | The DS250x is a 512/1024bit add-only PROM(you can add data but cannot change the old one) that's used mainly for device identification purposes 5 | like serial number, mfgr data, unique identifiers, etc. It uses the Maxim 1-wire bus. 6 | 7 | This sketch will use the SKIP ROM function that skips the 1-Wire search phase since we only have one device connected in the bus on digital pin 6. 8 | If more than one device is connected to the bus, it will fail. 9 | Sketch will not verify if device connected is from the DS250x family since the skip rom function effectively skips the family-id byte readout. 10 | thus it is possible to run this sketch with any Maxim OneWire device in which case the command CRC will most likely fail. 11 | Sketch will only read the first page of memory(32bits) starting from the lower address(0000h), if more than 1 device is present, then use the sketch with search functions. 12 | Remember to put a 4.7K pullup resistor between pin 6 and +Vcc 13 | 14 | To change the range or ammount of data to read, simply change the data array size, LSB/MSB addresses and for loop iterations 15 | 16 | This example code is in the public domain and is provided AS-IS. 17 | 18 | Built with Arduino 0022 and PJRC OneWire 2.0 library http://www.pjrc.com/teensy/td_libs_OneWire.html 19 | 20 | created by Guillermo Lovato 21 | march/2011 22 | 23 | */ 24 | 25 | #include 26 | OneWire ds(2); // OneWire bus on digital pin 2 27 | void setup() { 28 | Serial.begin (9600); 29 | } 30 | 31 | void loop() { 32 | byte i; // This is for the for loops 33 | boolean present; // device present var 34 | byte data[32]; // container for the data from device 35 | byte leemem[3] = { // array with the commands to initiate a read, DS250x devices expect 3 bytes to start a read: command,LSB&MSB adresses 36 | 0xF0 , 0x00 , 0x00 }; // 0xF0 is the Read Data command, followed by 00h 00h as starting address(the beginning, 0000h) 37 | byte ccrc; // Variable to store the command CRC 38 | byte ccrc_calc; 39 | 40 | present = ds.reset(); // OneWire bus reset, always needed to start operation on the bus, returns a 1/TRUE if there's a device present. 41 | ds.skip(); // Skip ROM search 42 | 43 | if (present == TRUE){ // We only try to read the data if there's a device present 44 | Serial.println("DS250x device present"); 45 | ds.write(leemem[0],1); // Read data command, leave ghost power on 46 | ds.write(leemem[1],1); // LSB starting address, leave ghost power on 47 | ds.write(leemem[2],1); // MSB starting address, leave ghost power on 48 | 49 | ccrc = ds.read(); // DS250x generates a CRC for the command we sent, we assign a read slot and store it's value 50 | ccrc_calc = OneWire::crc8(leemem, 3); // We calculate the CRC of the commands we sent using the library function and store it 51 | 52 | if ( ccrc_calc != ccrc) { // Then we compare it to the value the ds250x calculated, if it fails, we print debug messages and abort 53 | Serial.println("Invalid command CRC!"); 54 | Serial.print("Calculated CRC:"); 55 | Serial.println(ccrc_calc,HEX); // HEX makes it easier to observe and compare 56 | Serial.print("DS250x readback CRC:"); 57 | Serial.println(ccrc,HEX); 58 | return; // Since CRC failed, we abort the rest of the loop and start over 59 | } 60 | Serial.println("Data is: "); // For the printout of the data 61 | for ( i = 0; i < 32; i++) { // Now it's time to read the PROM data itself, each page is 32 bytes so we need 32 read commands 62 | data[i] = ds.read(); // we store each read byte to a different position in the data array 63 | Serial.print(data[i]); // printout in ASCII 64 | Serial.print(" "); // blank space 65 | } 66 | Serial.println(); 67 | delay(5000); // Delay so we don't saturate the serial output 68 | } 69 | else { // Nothing is connected in the bus 70 | Serial.println("Nothing connected"); 71 | delay(3000); 72 | } 73 | } 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /ArduFarmBot2_Local_Automatic_Ctrl_V2/ArduFarmBot2_Local_Automatic_Ctrl_V2.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************************** 2 | * ArduFarmBot using NodeMCU ESP-12 Develop Kit V1.0 3 | * DHT connected to NodeMCU pin D3 (Ambient Temperature and Relative Humidity) 4 | * Soil Moister Sensor connected to A0 5 | * Sensor Data on local OLED Display 6 | * Local Command via buttons 7 | * OLED Display is off as default. Press Sensor Button to update and display data 8 | * Introduced the function "waitButtonPress (int waitTime)", to break initial loop 9 | * Automatic Local Control 10 | * Display automatic set-up parameters at Start-up 11 | * 12 | * Version 2.0 - Automatic and Local Control - Developed by MJRovai 15 Feb 2017 13 | ********************************************************************************************************************************/ 14 | #define SW_VERSION " SW Ver. 2.0" // SW version will appears at innitial LCD Display 15 | #include "stationDefines.h" // Project definitions 16 | 17 | /* ESP */ 18 | #include 19 | 20 | /* TIMER */ 21 | #include 22 | SimpleTimer timer; 23 | 24 | /* OLED */ 25 | #include // library for OLED: SCL ==> D1; SDA ==> D2 26 | #include 27 | #include 28 | 29 | /* DHT22*/ 30 | #include "DHT.h" 31 | DHT dht(DHTPIN, DHTTYPE); 32 | 33 | /* DS18B20 Temperature Sensor */ 34 | #include 35 | #include 36 | OneWire oneWire(ONE_WIRE_BUS); 37 | DallasTemperature DS18B20(&oneWire); 38 | 39 | void setup() 40 | { 41 | Serial.begin(115200); 42 | delay(10); 43 | Serial.println("ArduFarmBot 2"); 44 | Serial.println(".... Starting Setup"); 45 | Serial.println(" "); 46 | 47 | pinMode(PUMP_PIN, OUTPUT); 48 | pinMode(LAMP_PIN, OUTPUT); 49 | pinMode(PUMP_ON_BUTTON, INPUT_PULLUP); 50 | pinMode(LAMP_ON_BUTTON, INPUT_PULLUP); 51 | pinMode(SENSORS_READ_BUTTON, INPUT_PULLUP); 52 | pinMode(soilMoisterVcc, OUTPUT); 53 | 54 | oledStart(); 55 | dht.begin(); 56 | DS18B20.begin(); 57 | 58 | digitalWrite(PUMP_PIN, LOW); 59 | digitalWrite(LAMP_PIN, LOW); 60 | digitalWrite (soilMoisterVcc, LOW); 61 | 62 | waitButtonPress (SHOW_SET_UP); // Wait for Sensor Button to be pressed 63 | oled.clearDisplay(); 64 | startTimers(); 65 | } 66 | 67 | void loop() 68 | { 69 | timer.run(); // Initiates SimpleTimer 70 | } 71 | 72 | /**************************************************************** 73 | * Read local commands (Pump and Lamp buttons are normally "HIGH"): 74 | ****************************************************************/ 75 | void readLocalCmd() 76 | { 77 | boolean digiValue = debounce(PUMP_ON_BUTTON); 78 | if (!digiValue) 79 | { 80 | pumpStatus = !pumpStatus; 81 | aplyCmd(); 82 | } 83 | 84 | digiValue = debounce(LAMP_ON_BUTTON); 85 | if (!digiValue) 86 | { 87 | lampStatus = !lampStatus; 88 | aplyCmd(); 89 | } 90 | 91 | digiValue = debounce(SENSORS_READ_BUTTON); 92 | if (!digiValue) 93 | { 94 | turnOffOLED = !turnOffOLED; 95 | if (!turnOffOLED) 96 | { 97 | oled.setTextXY(0,0); oled.putString("UPDATING SENSORS"); 98 | getDhtData(); 99 | getSoilMoisterData(); 100 | getSoilTempData(); 101 | oledStart(); 102 | displayData(); 103 | }else oled.clearDisplay(); 104 | } 105 | } 106 | 107 | /*************************************************** 108 | * Receive Commands and act on actuators 109 | ****************************************************/ 110 | void aplyCmd() 111 | { 112 | if (pumpStatus == 1) 113 | { 114 | digitalWrite(PUMP_PIN, HIGH); 115 | if (!turnOffOLED) displayData(); 116 | } 117 | else 118 | { 119 | digitalWrite(PUMP_PIN, LOW); 120 | if (!turnOffOLED) displayData(); 121 | } 122 | 123 | if (lampStatus == 1) 124 | { 125 | digitalWrite(LAMP_PIN, HIGH); 126 | if (!turnOffOLED) displayData(); 127 | } 128 | else 129 | { 130 | digitalWrite(LAMP_PIN, LOW); 131 | if (!turnOffOLED) displayData(); 132 | } 133 | } 134 | 135 | /*************************************************** 136 | * Automatically Control the Plantation based on sensors reading 137 | ****************************************************/ 138 | void autoControlPlantation(void) 139 | { 140 | if (soilMoister < DRY_SOIL) 141 | { 142 | turnPumpOn(); 143 | } 144 | 145 | if (airTemp < COLD_TEMP) 146 | { 147 | turnLampOn(); 148 | } 149 | } 150 | 151 | /*************************************************** 152 | * Turn Pump On for a certain amount of time 153 | ****************************************************/ 154 | void turnPumpOn() 155 | { 156 | pumpStatus = 1; 157 | aplyCmd(); 158 | delay (TIME_PUMP_ON*1000); 159 | pumpStatus = 0; 160 | aplyCmd(); 161 | } 162 | 163 | /*************************************************** 164 | * Turn Lamp On for a certain amount of time 165 | ****************************************************/ 166 | void turnLampOn() 167 | { 168 | lampStatus = 1; 169 | aplyCmd(); 170 | delay (TIME_LAMP_ON*1000); 171 | lampStatus = 0; 172 | aplyCmd(); 173 | } 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V3_0/ArduFarmBot2_Ext_Auto_Ctrl__V3_0.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************************** 2 | * ArduFarmBot using NodeMCU ESP-12 Develop Kit V1.0 3 | * DHT connected to NodeMCU pin D3 (Ambient Temperature and Relative Humidity) 4 | * Soil Moister Sensor connected to A0 5 | * Sensor Data on local OLED Display 6 | * Local Command via buttons 7 | * OLED Display is off as default. Press Sensor Button to update and display data 8 | * Introduced the function "waitButtonPress (int waitTime)", to break initial loop 9 | * Automatic Local Control 10 | * Display automatic set-up parameters at Start-up 11 | * Sensor data sent to Blynk app 12 | * Control commands received from Blynk app 13 | * Downloads, docs, tutorials: http://www.blynk.cc 14 | * Blynk library is licensed under MIT license 15 | * 16 | * MJRoBot Version 3.0 - Automatic and Remote Control Developed by MJRovai 16 Feb 2017 17 | ********************************************************************************************************************************/ 18 | #define SW_VERSION " SW Ver. 3.0" // SW version will appears at innitial LCD Display 19 | #include "stationDefines.h" // Project definitions 20 | #include "stationCredentials.h" 21 | 22 | /* ESP & Blynk */ 23 | #define BLYNK_PRINT Serial // Comment this out to disable prints and save space 24 | #include 25 | #include 26 | WidgetLED PUMPs(V0); // Echo signal to Sensors Tab at Blynk App 27 | WidgetLED PUMPa(V5); // Echo signal to Actuators Tab at Blynk App 28 | WidgetLED LAMPs(V1); // Echo signal to Sensors Tab at Blynk App 29 | WidgetLED LAMPa(V6); // Echo signal to Actuators Tab at Blynk App 30 | 31 | /* TIMER */ 32 | #include 33 | SimpleTimer timer; 34 | 35 | /* OLED */ 36 | #include // library for OLED: SCL ==> D1; SDA ==> D2 37 | #include 38 | #include 39 | 40 | /* DHT22*/ 41 | #include "DHT.h" 42 | DHT dht(DHTPIN, DHTTYPE); 43 | 44 | /* DS18B20 Temperature Sensor */ 45 | #include 46 | #include 47 | OneWire oneWire(ONE_WIRE_BUS); 48 | DallasTemperature DS18B20(&oneWire); 49 | 50 | void setup() 51 | { 52 | Serial.begin(115200); 53 | delay(10); 54 | Serial.println("ArduFarmBot 2"); 55 | Serial.println(".... Starting Setup"); 56 | Serial.println(" "); 57 | 58 | pinMode(PUMP_PIN, OUTPUT); 59 | pinMode(LAMP_PIN, OUTPUT); 60 | pinMode(PUMP_ON_BUTTON, INPUT_PULLUP); 61 | pinMode(LAMP_ON_BUTTON, INPUT_PULLUP); 62 | pinMode(SENSORS_READ_BUTTON, INPUT_PULLUP); 63 | pinMode(soilMoisterVcc, OUTPUT); 64 | 65 | Blynk.begin(auth, ssid, pass); 66 | oledStart(); 67 | dht.begin(); 68 | DS18B20.begin(); 69 | 70 | PUMPs.off(); 71 | LAMPs.off(); 72 | PUMPa.off(); 73 | LAMPa.off(); 74 | digitalWrite(PUMP_PIN, LOW); 75 | digitalWrite(LAMP_PIN, LOW); 76 | digitalWrite (soilMoisterVcc, LOW); 77 | 78 | waitButtonPress (SHOW_SET_UP); // Wait for Sensor Button to be pressed 79 | oled.clearDisplay(); 80 | startTimers(); 81 | } 82 | 83 | void loop() 84 | { 85 | timer.run(); // Initiates SimpleTimer 86 | Blynk.run(); 87 | } 88 | 89 | /**************************************************************** 90 | * Read remote commands 91 | ****************************************************************/ 92 | BLYNK_WRITE(3) // Pump remote control 93 | { 94 | int i=param.asInt(); 95 | if (i==1) 96 | { 97 | pumpStatus = !pumpStatus; 98 | aplyCmd(); 99 | } 100 | } 101 | 102 | BLYNK_WRITE(4) // Lamp remote control 103 | { 104 | int i=param.asInt(); 105 | if (i==1) 106 | { 107 | lampStatus = !lampStatus; 108 | aplyCmd(); 109 | } 110 | } 111 | 112 | /**************************************************************** 113 | * Read local commands (Pump and Lamp buttons are normally "HIGH"): 114 | ****************************************************************/ 115 | void readLocalCmd() 116 | { 117 | boolean digiValue = debounce(PUMP_ON_BUTTON); 118 | if (!digiValue) 119 | { 120 | pumpStatus = !pumpStatus; 121 | aplyCmd(); 122 | } 123 | 124 | digiValue = debounce(LAMP_ON_BUTTON); 125 | if (!digiValue) 126 | { 127 | lampStatus = !lampStatus; 128 | aplyCmd(); 129 | } 130 | 131 | digiValue = debounce(SENSORS_READ_BUTTON); 132 | if (!digiValue) 133 | { 134 | turnOffOLED = !turnOffOLED; 135 | if (!turnOffOLED) 136 | { 137 | oled.setTextXY(0,0); oled.putString("UPDATING SENSORS"); 138 | getDhtData(); 139 | getSoilMoisterData(); 140 | getSoilTempData(); 141 | oledStart(); 142 | displayData(); 143 | }else oled.clearDisplay(); 144 | } 145 | } 146 | 147 | /*************************************************** 148 | * Receive Commands and act on actuators 149 | ****************************************************/ 150 | void aplyCmd() 151 | { 152 | if (pumpStatus == 1) 153 | { 154 | Blynk.notify("ArduFarmBot2: Warning ==>> Pump ON"); 155 | digitalWrite(PUMP_PIN, HIGH); 156 | if (!turnOffOLED) displayData(); 157 | PUMPs.on(); 158 | PUMPa.on(); 159 | } 160 | else 161 | { 162 | digitalWrite(PUMP_PIN, LOW); 163 | if (!turnOffOLED) displayData(); 164 | PUMPs.off(); 165 | PUMPa.off(); 166 | } 167 | 168 | if (lampStatus == 1) 169 | { 170 | Blynk.notify("ArduFarmBot2: Warning ==>> Lamp ON"); 171 | digitalWrite(LAMP_PIN, HIGH); 172 | if (!turnOffOLED) displayData(); 173 | LAMPs.on(); 174 | LAMPa.on(); 175 | } 176 | else 177 | { 178 | digitalWrite(LAMP_PIN, LOW); 179 | if (!turnOffOLED) displayData(); 180 | LAMPs.off(); 181 | LAMPa.off(); 182 | } 183 | } 184 | 185 | /*************************************************** 186 | * Automatically Control the Plantation based on sensors reading 187 | ****************************************************/ 188 | void autoControlPlantation(void) 189 | { 190 | if (soilMoister < DRY_SOIL) 191 | { 192 | turnPumpOn(); 193 | } 194 | 195 | if (airTemp < COLD_TEMP) 196 | { 197 | turnLampOn(); 198 | } 199 | } 200 | 201 | /*************************************************** 202 | * Turn Pump On for a certain amount of time 203 | ****************************************************/ 204 | void turnPumpOn() 205 | { 206 | pumpStatus = 1; 207 | aplyCmd(); 208 | delay (TIME_PUMP_ON*1000); 209 | pumpStatus = 0; 210 | aplyCmd(); 211 | } 212 | 213 | /*************************************************** 214 | * Turn Lamp On for a certain amount of time 215 | ****************************************************/ 216 | void turnLampOn() 217 | { 218 | lampStatus = 1; 219 | aplyCmd(); 220 | delay (TIME_LAMP_ON*1000); 221 | lampStatus = 0; 222 | aplyCmd(); 223 | } 224 | 225 | /*************************************************** 226 | * Send data to Blynk 227 | **************************************************/ 228 | void sendUptime() 229 | { 230 | Blynk.virtualWrite(10, airTemp); //virtual pin V10 231 | Blynk.virtualWrite(11, airHum); // virtual pin V11 232 | Blynk.virtualWrite(12, soilMoister); // virtual pin V12 233 | Blynk.virtualWrite(13, soilTemp); //virtual pin V13 234 | } 235 | 236 | 237 | -------------------------------------------------------------------------------- /ArduFarmBot2_Ext_Auto_Ctrl__V4_0/ArduFarmBot2_Ext_Auto_Ctrl__V4_0.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************************** 2 | * ArduFarmBot using NodeMCU ESP-12 Develop Kit V1.0 3 | * DHT connected to NodeMCU pin D3 (Ambient Temperature and Relative Humidity) 4 | * Soil Moister Sensor connected to A0 5 | * Sensor Data on local OLED Display 6 | * Local Command via buttons 7 | * OLED Display is off as default. Press Sensor Button to update and display data 8 | * Introduced the function "waitButtonPress (int waitTime)", to break initial loop 9 | * Automatic Local Control 10 | * Display automatic set-up parameters at Start-up 11 | * Sensor data sent to Blynk app 12 | * Control commands received from Blynk app 13 | * Downloads, docs, tutorials: http://www.blynk.cc 14 | * Blynk library is licensed under MIT license 15 | * 16 | * V4.0 Invert the logic to use Relay module that works from HIGH to LOW 17 | * 18 | * MJRoBot Version 4.0 - Automatic and Remote Control - Logic LOW - Developed by MJRovai 16 Feb 2017 19 | ********************************************************************************************************************************/ 20 | #define SW_VERSION " SW Ver. 4.0" // SW version will appears at innitial LCD Display 21 | #include "stationDefines.h" // Project definitions 22 | #include "stationCredentials.h" 23 | 24 | /* ESP & Blynk */ 25 | #define BLYNK_PRINT Serial // Comment this out to disable prints and save space 26 | #include 27 | #include 28 | WidgetLED PUMPs(V0); // Echo signal to Sensors Tab at Blynk App 29 | WidgetLED PUMPa(V5); // Echo signal to Actuators Tab at Blynk App 30 | WidgetLED LAMPs(V1); // Echo signal to Sensors Tab at Blynk App 31 | WidgetLED LAMPa(V6); // Echo signal to Actuators Tab at Blynk App 32 | 33 | /* TIMER */ 34 | #include 35 | SimpleTimer timer; 36 | 37 | /* OLED */ 38 | #include // library for OLED: SCL ==> D1; SDA ==> D2 39 | #include 40 | #include 41 | 42 | /* DHT22*/ 43 | #include "DHT.h" 44 | DHT dht(DHTPIN, DHTTYPE); 45 | 46 | /* DS18B20 Temperature Sensor */ 47 | #include 48 | #include 49 | OneWire oneWire(ONE_WIRE_BUS); 50 | DallasTemperature DS18B20(&oneWire); 51 | 52 | void setup() 53 | { 54 | Serial.begin(115200); 55 | delay(10); 56 | Serial.println("ArduFarmBot 2"); 57 | Serial.println(".... Starting Setup"); 58 | Serial.println(" "); 59 | 60 | pinMode(PUMP_PIN, OUTPUT); 61 | pinMode(LAMP_PIN, OUTPUT); 62 | pinMode(PUMP_ON_BUTTON, INPUT_PULLUP); 63 | pinMode(LAMP_ON_BUTTON, INPUT_PULLUP); 64 | pinMode(SENSORS_READ_BUTTON, INPUT_PULLUP); 65 | pinMode(soilMoisterVcc, OUTPUT); 66 | 67 | Blynk.begin(auth, ssid, pass); 68 | oledStart(); 69 | dht.begin(); 70 | DS18B20.begin(); 71 | 72 | PUMPs.off(); 73 | LAMPs.off(); 74 | PUMPa.off(); 75 | LAMPa.off(); 76 | digitalWrite(PUMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH) 77 | digitalWrite(LAMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH) 78 | digitalWrite (soilMoisterVcc, LOW); 79 | 80 | waitButtonPress (SHOW_SET_UP); // Wait for Sensor Button to be pressed 81 | oled.clearDisplay(); 82 | startTimers(); 83 | } 84 | 85 | void loop() 86 | { 87 | timer.run(); // Initiates SimpleTimer 88 | Blynk.run(); 89 | } 90 | 91 | /**************************************************************** 92 | * Read remote commands 93 | ****************************************************************/ 94 | BLYNK_WRITE(3) // Pump remote control 95 | { 96 | int i=param.asInt(); 97 | if (i==1) 98 | { 99 | pumpStatus = !pumpStatus; 100 | aplyCmd(); 101 | } 102 | } 103 | 104 | BLYNK_WRITE(4) // Lamp remote control 105 | { 106 | int i=param.asInt(); 107 | if (i==1) 108 | { 109 | lampStatus = !lampStatus; 110 | aplyCmd(); 111 | } 112 | } 113 | 114 | /**************************************************************** 115 | * Read local commands (Pump and Lamp buttons are normally "HIGH"): 116 | ****************************************************************/ 117 | void readLocalCmd() 118 | { 119 | boolean digiValue = debounce(PUMP_ON_BUTTON); 120 | if (!digiValue) 121 | { 122 | pumpStatus = !pumpStatus; 123 | aplyCmd(); 124 | } 125 | 126 | digiValue = debounce(LAMP_ON_BUTTON); 127 | if (!digiValue) 128 | { 129 | lampStatus = !lampStatus; 130 | aplyCmd(); 131 | } 132 | 133 | digiValue = debounce(SENSORS_READ_BUTTON); 134 | if (!digiValue) 135 | { 136 | turnOffOLED = !turnOffOLED; 137 | if (!turnOffOLED) 138 | { 139 | oled.setTextXY(0,0); oled.putString("UPDATING SENSORS"); 140 | getDhtData(); 141 | getSoilMoisterData(); 142 | getSoilTempData(); 143 | oledStart(); 144 | displayData(); 145 | }else oled.clearDisplay(); 146 | } 147 | } 148 | 149 | /*************************************************** 150 | * Receive Commands and act on RELAYs - Logic LOW 151 | ****************************************************/ 152 | void aplyCmd() 153 | { 154 | if (pumpStatus == 1) 155 | { 156 | Blynk.notify("ArduFarmBot2: Warning ==>> Pump ON"); 157 | digitalWrite(PUMP_PIN, LOW); // To be used with Relay module (inverted logic: activate with LOW) 158 | if (!turnOffOLED) displayData(); 159 | PUMPs.on(); 160 | PUMPa.on(); 161 | } 162 | else 163 | { 164 | digitalWrite(PUMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH) 165 | if (!turnOffOLED) displayData(); 166 | PUMPs.off(); 167 | PUMPa.off(); 168 | } 169 | 170 | if (lampStatus == 1) 171 | { 172 | Blynk.notify("ArduFarmBot2: Warning ==>> Lamp ON"); 173 | digitalWrite(LAMP_PIN, LOW); // To be used with Relay module (inverted logic: activate with LOW) 174 | if (!turnOffOLED) displayData(); 175 | LAMPs.on(); 176 | LAMPa.on(); 177 | } 178 | else 179 | { 180 | digitalWrite(LAMP_PIN, HIGH); // To be used with Relay module (inverted logic: normally HIGH) 181 | if (!turnOffOLED) displayData(); 182 | LAMPs.off(); 183 | LAMPa.off(); 184 | } 185 | } 186 | 187 | /*************************************************** 188 | * Automatically Control the Plantation based on sensors reading 189 | ****************************************************/ 190 | void autoControlPlantation(void) 191 | { 192 | if (soilMoister < DRY_SOIL) 193 | { 194 | turnPumpOn(); 195 | } 196 | 197 | if (airTemp < COLD_TEMP) 198 | { 199 | turnLampOn(); 200 | } 201 | } 202 | 203 | /*************************************************** 204 | * Turn Pump On for a certain amount of time 205 | ****************************************************/ 206 | void turnPumpOn() 207 | { 208 | pumpStatus = 1; 209 | aplyCmd(); 210 | delay (TIME_PUMP_ON*1000); 211 | pumpStatus = 0; 212 | aplyCmd(); 213 | } 214 | 215 | /*************************************************** 216 | * Turn Lamp On for a certain amount of time 217 | ****************************************************/ 218 | void turnLampOn() 219 | { 220 | lampStatus = 1; 221 | aplyCmd(); 222 | delay (TIME_LAMP_ON*1000); 223 | lampStatus = 0; 224 | aplyCmd(); 225 | } 226 | 227 | /*************************************************** 228 | * Send data to Blynk 229 | **************************************************/ 230 | void sendUptime() 231 | { 232 | Blynk.virtualWrite(10, airTemp); //virtual pin V10 233 | Blynk.virtualWrite(11, airHum); // virtual pin V11 234 | Blynk.virtualWrite(12, soilMoister); // virtual pin V12 235 | Blynk.virtualWrite(13, soilTemp); //virtual pin V13 236 | } 237 | 238 | 239 | -------------------------------------------------------------------------------- /OneWire/OneWire.h: -------------------------------------------------------------------------------- 1 | #ifndef OneWire_h 2 | #define OneWire_h 3 | 4 | #include 5 | 6 | #if ARDUINO >= 100 7 | #include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc 8 | #else 9 | #include "WProgram.h" // for delayMicroseconds 10 | #include "pins_arduino.h" // for digitalPinToBitMask, etc 11 | #endif 12 | 13 | // You can exclude certain features from OneWire. In theory, this 14 | // might save some space. In practice, the compiler automatically 15 | // removes unused code (technically, the linker, using -fdata-sections 16 | // and -ffunction-sections when compiling, and Wl,--gc-sections 17 | // when linking), so most of these will not result in any code size 18 | // reduction. Well, unless you try to use the missing features 19 | // and redesign your program to not need them! ONEWIRE_CRC8_TABLE 20 | // is the exception, because it selects a fast but large algorithm 21 | // or a small but slow algorithm. 22 | 23 | // you can exclude onewire_search by defining that to 0 24 | #ifndef ONEWIRE_SEARCH 25 | #define ONEWIRE_SEARCH 1 26 | #endif 27 | 28 | // You can exclude CRC checks altogether by defining this to 0 29 | #ifndef ONEWIRE_CRC 30 | #define ONEWIRE_CRC 1 31 | #endif 32 | 33 | // Select the table-lookup method of computing the 8-bit CRC 34 | // by setting this to 1. The lookup table enlarges code size by 35 | // about 250 bytes. It does NOT consume RAM (but did in very 36 | // old versions of OneWire). If you disable this, a slower 37 | // but very compact algorithm is used. 38 | #ifndef ONEWIRE_CRC8_TABLE 39 | #define ONEWIRE_CRC8_TABLE 1 40 | #endif 41 | 42 | // You can allow 16-bit CRC checks by defining this to 1 43 | // (Note that ONEWIRE_CRC must also be 1.) 44 | #ifndef ONEWIRE_CRC16 45 | #define ONEWIRE_CRC16 1 46 | #endif 47 | 48 | #define FALSE 0 49 | #define TRUE 1 50 | 51 | // Platform specific I/O definitions 52 | 53 | #if defined(__AVR__) 54 | #define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) 55 | #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) 56 | #define IO_REG_TYPE uint8_t 57 | #define IO_REG_ASM asm("r30") 58 | #define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) 59 | #define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) 60 | #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) 61 | #define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) 62 | #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) 63 | 64 | #elif defined(__MK20DX128__) 65 | #define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) 66 | #define PIN_TO_BITMASK(pin) (1) 67 | #define IO_REG_TYPE uint8_t 68 | #define IO_REG_ASM 69 | #define DIRECT_READ(base, mask) (*((base)+512)) 70 | #define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) 71 | #define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) 72 | #define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) 73 | #define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) 74 | 75 | #elif defined(__SAM3X8E__) 76 | // Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due. 77 | // http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268 78 | // If you have trouble with OneWire on Arduino Due, please check the 79 | // status of delayMicroseconds() before reporting a bug in OneWire! 80 | #define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER)) 81 | #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) 82 | #define IO_REG_TYPE uint32_t 83 | #define IO_REG_ASM 84 | #define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) 85 | #define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) 86 | #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) 87 | #define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) 88 | #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) 89 | #ifndef PROGMEM 90 | #define PROGMEM 91 | #endif 92 | #ifndef pgm_read_byte 93 | #define pgm_read_byte(addr) (*(const uint8_t *)(addr)) 94 | #endif 95 | 96 | #elif defined(__PIC32MX__) 97 | #define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin))) 98 | #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) 99 | #define IO_REG_TYPE uint32_t 100 | #define IO_REG_ASM 101 | #define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10 102 | #define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08 103 | #define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04 104 | #define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24 105 | #define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28 106 | 107 | #elif defined(ARDUINO_ARCH_ESP8266) 108 | #define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) 109 | #define PIN_TO_BITMASK(pin) (1 << pin) 110 | #define IO_REG_TYPE uint32_t 111 | #define IO_REG_ASM 112 | #define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS 113 | #define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS 114 | #define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS 115 | #define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS 116 | #define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS 117 | 118 | #else 119 | #error "Please define I/O register types here" 120 | #endif 121 | 122 | 123 | class OneWire 124 | { 125 | private: 126 | IO_REG_TYPE bitmask; 127 | volatile IO_REG_TYPE *baseReg; 128 | 129 | #if ONEWIRE_SEARCH 130 | // global search state 131 | unsigned char ROM_NO[8]; 132 | uint8_t LastDiscrepancy; 133 | uint8_t LastFamilyDiscrepancy; 134 | uint8_t LastDeviceFlag; 135 | #endif 136 | 137 | public: 138 | OneWire(uint8_t pin, bool pullup = true); 139 | 140 | // Perform a 1-Wire reset cycle. Returns 1 if a device responds 141 | // with a presence pulse. Returns 0 if there is no device or the 142 | // bus is shorted or otherwise held low for more than 250uS 143 | uint8_t reset(void); 144 | 145 | // Issue a 1-Wire rom select command, you do the reset first. 146 | void select(const uint8_t rom[8]); 147 | 148 | // Issue a 1-Wire rom skip command, to address all on bus. 149 | void skip(void); 150 | 151 | // Write a byte. If 'power' is one then the wire is held high at 152 | // the end for parasitically powered devices. You are responsible 153 | // for eventually depowering it by calling depower() or doing 154 | // another read or write. 155 | void write(uint8_t v, uint8_t power = 0); 156 | 157 | void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0); 158 | 159 | // Read a byte. 160 | uint8_t read(void); 161 | 162 | void read_bytes(uint8_t *buf, uint16_t count); 163 | 164 | // Write a bit. The bus is always left powered at the end, see 165 | // note in write() about that. 166 | void write_bit(uint8_t v); 167 | 168 | // Read a bit. 169 | uint8_t read_bit(void); 170 | 171 | // Stop forcing power onto the bus. You only need to do this if 172 | // you used the 'power' flag to write() or used a write_bit() call 173 | // and aren't about to do another read or write. You would rather 174 | // not leave this powered if you don't have to, just in case 175 | // someone shorts your bus. 176 | void depower(void); 177 | 178 | #if ONEWIRE_SEARCH 179 | // Clear the search state so that if will start from the beginning again. 180 | void reset_search(); 181 | 182 | // Setup the search to find the device type 'family_code' on the next call 183 | // to search(*newAddr) if it is present. 184 | void target_search(uint8_t family_code); 185 | 186 | // Look for the next device. Returns 1 if a new address has been 187 | // returned. A zero might mean that the bus is shorted, there are 188 | // no devices, or you have already retrieved all of them. It 189 | // might be a good idea to check the CRC to make sure you didn't 190 | // get garbage. The order is deterministic. You will always get 191 | // the same devices in the same order. 192 | uint8_t search(uint8_t *newAddr); 193 | #endif 194 | 195 | #if ONEWIRE_CRC 196 | // Compute a Dallas Semiconductor 8 bit CRC, these are used in the 197 | // ROM and scratchpad registers. 198 | static uint8_t crc8(const uint8_t *addr, uint8_t len); 199 | 200 | #if ONEWIRE_CRC16 201 | // Compute the 1-Wire CRC16 and compare it against the received CRC. 202 | // Example usage (reading a DS2408): 203 | // // Put everything in a buffer so we can compute the CRC easily. 204 | // uint8_t buf[13]; 205 | // buf[0] = 0xF0; // Read PIO Registers 206 | // buf[1] = 0x88; // LSB address 207 | // buf[2] = 0x00; // MSB address 208 | // WriteBytes(net, buf, 3); // Write 3 cmd bytes 209 | // ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16 210 | // if (!CheckCRC16(buf, 11, &buf[11])) { 211 | // // Handle error. 212 | // } 213 | // 214 | // @param input - Array of bytes to checksum. 215 | // @param len - How many bytes to use. 216 | // @param inverted_crc - The two CRC16 bytes in the received data. 217 | // This should just point into the received data, 218 | // *not* at a 16-bit integer. 219 | // @param crc - The crc starting value (optional) 220 | // @return True, iff the CRC matches. 221 | static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0); 222 | 223 | // Compute a Dallas Semiconductor 16 bit CRC. This is required to check 224 | // the integrity of data received from many 1-Wire devices. Note that the 225 | // CRC computed here is *not* what you'll get from the 1-Wire network, 226 | // for two reasons: 227 | // 1) The CRC is transmitted bitwise inverted. 228 | // 2) Depending on the endian-ness of your processor, the binary 229 | // representation of the two-byte return value may have a different 230 | // byte order than the two bytes you get from 1-Wire. 231 | // @param input - Array of bytes to checksum. 232 | // @param len - How many bytes to use. 233 | // @param crc - The crc starting value (optional) 234 | // @return The CRC16, as defined by Dallas Semiconductor. 235 | static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0); 236 | #endif 237 | #endif 238 | }; 239 | 240 | #endif 241 | -------------------------------------------------------------------------------- /OneWire/OneWire.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2007, Jim Studt (original old version - many contributors since) 3 | 4 | The latest version of this library may be found at: 5 | http://www.pjrc.com/teensy/td_libs_OneWire.html 6 | 7 | OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since 8 | January 2010. At the time, it was in need of many bug fixes, but had 9 | been abandoned the original author (Jim Studt). None of the known 10 | contributors were interested in maintaining OneWire. Paul typically 11 | works on OneWire every 6 to 12 months. Patches usually wait that 12 | long. If anyone is interested in more actively maintaining OneWire, 13 | please contact Paul. 14 | 15 | Version 2.2: 16 | Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com 17 | Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030 18 | Fix DS18B20 example negative temperature 19 | Fix DS18B20 example's low res modes, Ken Butcher 20 | Improve reset timing, Mark Tillotson 21 | Add const qualifiers, Bertrik Sikken 22 | Add initial value input to crc16, Bertrik Sikken 23 | Add target_search() function, Scott Roberts 24 | 25 | Version 2.1: 26 | Arduino 1.0 compatibility, Paul Stoffregen 27 | Improve temperature example, Paul Stoffregen 28 | DS250x_PROM example, Guillermo Lovato 29 | PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com 30 | Improvements from Glenn Trewitt: 31 | - crc16() now works 32 | - check_crc16() does all of calculation/checking work. 33 | - Added read_bytes() and write_bytes(), to reduce tedious loops. 34 | - Added ds2408 example. 35 | Delete very old, out-of-date readme file (info is here) 36 | 37 | Version 2.0: Modifications by Paul Stoffregen, January 2010: 38 | http://www.pjrc.com/teensy/td_libs_OneWire.html 39 | Search fix from Robin James 40 | http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 41 | Use direct optimized I/O in all cases 42 | Disable interrupts during timing critical sections 43 | (this solves many random communication errors) 44 | Disable interrupts during read-modify-write I/O 45 | Reduce RAM consumption by eliminating unnecessary 46 | variables and trimming many to 8 bits 47 | Optimize both crc8 - table version moved to flash 48 | 49 | Modified to work with larger numbers of devices - avoids loop. 50 | Tested in Arduino 11 alpha with 12 sensors. 51 | 26 Sept 2008 -- Robin James 52 | http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 53 | 54 | Updated to work with arduino-0008 and to include skip() as of 55 | 2007/07/06. --RJL20 56 | 57 | Modified to calculate the 8-bit CRC directly, avoiding the need for 58 | the 256-byte lookup table to be loaded in RAM. Tested in arduino-0010 59 | -- Tom Pollard, Jan 23, 2008 60 | 61 | Jim Studt's original library was modified by Josh Larios. 62 | 63 | Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008 64 | 65 | Permission is hereby granted, free of charge, to any person obtaining 66 | a copy of this software and associated documentation files (the 67 | "Software"), to deal in the Software without restriction, including 68 | without limitation the rights to use, copy, modify, merge, publish, 69 | distribute, sublicense, and/or sell copies of the Software, and to 70 | permit persons to whom the Software is furnished to do so, subject to 71 | the following conditions: 72 | 73 | The above copyright notice and this permission notice shall be 74 | included in all copies or substantial portions of the Software. 75 | 76 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 77 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 78 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 79 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 80 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 81 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 82 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 83 | 84 | Much of the code was inspired by Derek Yerger's code, though I don't 85 | think much of that remains. In any event that was.. 86 | (copyleft) 2006 by Derek Yerger - Free to distribute freely. 87 | 88 | The CRC code was excerpted and inspired by the Dallas Semiconductor 89 | sample code bearing this copyright. 90 | //--------------------------------------------------------------------------- 91 | // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. 92 | // 93 | // Permission is hereby granted, free of charge, to any person obtaining a 94 | // copy of this software and associated documentation files (the "Software"), 95 | // to deal in the Software without restriction, including without limitation 96 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 97 | // and/or sell copies of the Software, and to permit persons to whom the 98 | // Software is furnished to do so, subject to the following conditions: 99 | // 100 | // The above copyright notice and this permission notice shall be included 101 | // in all copies or substantial portions of the Software. 102 | // 103 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 104 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 105 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 106 | // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES 107 | // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 108 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 109 | // OTHER DEALINGS IN THE SOFTWARE. 110 | // 111 | // Except as contained in this notice, the name of Dallas Semiconductor 112 | // shall not be used except as stated in the Dallas Semiconductor 113 | // Branding Policy. 114 | //-------------------------------------------------------------------------- 115 | */ 116 | 117 | #include "OneWire.h" 118 | 119 | 120 | OneWire::OneWire(uint8_t pin, bool pullup) 121 | { 122 | if(pullup) { 123 | pinMode(pin, INPUT_PULLUP); 124 | } else { 125 | pinMode(pin, INPUT); 126 | } 127 | bitmask = PIN_TO_BITMASK(pin); 128 | baseReg = PIN_TO_BASEREG(pin); 129 | #if ONEWIRE_SEARCH 130 | reset_search(); 131 | #endif 132 | } 133 | 134 | 135 | // Perform the onewire reset function. We will wait up to 250uS for 136 | // the bus to come high, if it doesn't then it is broken or shorted 137 | // and we return a 0; 138 | // 139 | // Returns 1 if a device asserted a presence pulse, 0 otherwise. 140 | // 141 | uint8_t OneWire::reset(void) 142 | { 143 | IO_REG_TYPE mask = bitmask; 144 | volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; 145 | uint8_t r; 146 | uint8_t retries = 125; 147 | 148 | noInterrupts(); 149 | DIRECT_MODE_INPUT(reg, mask); 150 | interrupts(); 151 | // wait until the wire is high... just in case 152 | do { 153 | if (--retries == 0) return 0; 154 | delayMicroseconds(2); 155 | } while ( !DIRECT_READ(reg, mask)); 156 | 157 | noInterrupts(); 158 | DIRECT_WRITE_LOW(reg, mask); 159 | DIRECT_MODE_OUTPUT(reg, mask); // drive output low 160 | interrupts(); 161 | delayMicroseconds(480); 162 | noInterrupts(); 163 | DIRECT_MODE_INPUT(reg, mask); // allow it to float 164 | delayMicroseconds(70); 165 | r = !DIRECT_READ(reg, mask); 166 | interrupts(); 167 | delayMicroseconds(410); 168 | return r; 169 | } 170 | 171 | // 172 | // Write a bit. Port and bit is used to cut lookup time and provide 173 | // more certain timing. 174 | // 175 | void OneWire::write_bit(uint8_t v) 176 | { 177 | IO_REG_TYPE mask=bitmask; 178 | volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; 179 | 180 | if (v & 1) { 181 | noInterrupts(); 182 | DIRECT_WRITE_LOW(reg, mask); 183 | DIRECT_MODE_OUTPUT(reg, mask); // drive output low 184 | delayMicroseconds(10); 185 | DIRECT_WRITE_HIGH(reg, mask); // drive output high 186 | interrupts(); 187 | delayMicroseconds(55); 188 | } else { 189 | noInterrupts(); 190 | DIRECT_WRITE_LOW(reg, mask); 191 | DIRECT_MODE_OUTPUT(reg, mask); // drive output low 192 | delayMicroseconds(65); 193 | DIRECT_WRITE_HIGH(reg, mask); // drive output high 194 | interrupts(); 195 | delayMicroseconds(5); 196 | } 197 | } 198 | 199 | // 200 | // Read a bit. Port and bit is used to cut lookup time and provide 201 | // more certain timing. 202 | // 203 | uint8_t OneWire::read_bit(void) 204 | { 205 | IO_REG_TYPE mask=bitmask; 206 | volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; 207 | uint8_t r; 208 | 209 | noInterrupts(); 210 | DIRECT_MODE_OUTPUT(reg, mask); 211 | DIRECT_WRITE_LOW(reg, mask); 212 | delayMicroseconds(3); 213 | DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise 214 | delayMicroseconds(10); 215 | r = DIRECT_READ(reg, mask); 216 | interrupts(); 217 | delayMicroseconds(53); 218 | return r; 219 | } 220 | 221 | // 222 | // Write a byte. The writing code uses the active drivers to raise the 223 | // pin high, if you need power after the write (e.g. DS18S20 in 224 | // parasite power mode) then set 'power' to 1, otherwise the pin will 225 | // go tri-state at the end of the write to avoid heating in a short or 226 | // other mishap. 227 | // 228 | void OneWire::write(uint8_t v, uint8_t power /* = 0 */) { 229 | uint8_t bitMask; 230 | 231 | for (bitMask = 0x01; bitMask; bitMask <<= 1) { 232 | OneWire::write_bit( (bitMask & v)?1:0); 233 | } 234 | if ( !power) { 235 | noInterrupts(); 236 | DIRECT_MODE_INPUT(baseReg, bitmask); 237 | DIRECT_WRITE_LOW(baseReg, bitmask); 238 | interrupts(); 239 | } 240 | } 241 | 242 | void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) { 243 | for (uint16_t i = 0 ; i < count ; i++) 244 | write(buf[i]); 245 | if (!power) { 246 | noInterrupts(); 247 | DIRECT_MODE_INPUT(baseReg, bitmask); 248 | DIRECT_WRITE_LOW(baseReg, bitmask); 249 | interrupts(); 250 | } 251 | } 252 | 253 | // 254 | // Read a byte 255 | // 256 | uint8_t OneWire::read() { 257 | uint8_t bitMask; 258 | uint8_t r = 0; 259 | 260 | for (bitMask = 0x01; bitMask; bitMask <<= 1) { 261 | if ( OneWire::read_bit()) r |= bitMask; 262 | } 263 | return r; 264 | } 265 | 266 | void OneWire::read_bytes(uint8_t *buf, uint16_t count) { 267 | for (uint16_t i = 0 ; i < count ; i++) 268 | buf[i] = read(); 269 | } 270 | 271 | // 272 | // Do a ROM select 273 | // 274 | void OneWire::select(const uint8_t rom[8]) 275 | { 276 | uint8_t i; 277 | 278 | write(0x55); // Choose ROM 279 | 280 | for (i = 0; i < 8; i++) write(rom[i]); 281 | } 282 | 283 | // 284 | // Do a ROM skip 285 | // 286 | void OneWire::skip() 287 | { 288 | write(0xCC); // Skip ROM 289 | } 290 | 291 | void OneWire::depower() 292 | { 293 | noInterrupts(); 294 | DIRECT_MODE_INPUT(baseReg, bitmask); 295 | interrupts(); 296 | } 297 | 298 | #if ONEWIRE_SEARCH 299 | 300 | // 301 | // You need to use this function to start a search again from the beginning. 302 | // You do not need to do it for the first search, though you could. 303 | // 304 | void OneWire::reset_search() 305 | { 306 | // reset the search state 307 | LastDiscrepancy = 0; 308 | LastDeviceFlag = FALSE; 309 | LastFamilyDiscrepancy = 0; 310 | for(int i = 7; ; i--) { 311 | ROM_NO[i] = 0; 312 | if ( i == 0) break; 313 | } 314 | } 315 | 316 | // Setup the search to find the device type 'family_code' on the next call 317 | // to search(*newAddr) if it is present. 318 | // 319 | void OneWire::target_search(uint8_t family_code) 320 | { 321 | // set the search state to find SearchFamily type devices 322 | ROM_NO[0] = family_code; 323 | for (uint8_t i = 1; i < 8; i++) 324 | ROM_NO[i] = 0; 325 | LastDiscrepancy = 64; 326 | LastFamilyDiscrepancy = 0; 327 | LastDeviceFlag = FALSE; 328 | } 329 | 330 | // 331 | // Perform a search. If this function returns a '1' then it has 332 | // enumerated the next device and you may retrieve the ROM from the 333 | // OneWire::address variable. If there are no devices, no further 334 | // devices, or something horrible happens in the middle of the 335 | // enumeration then a 0 is returned. If a new device is found then 336 | // its address is copied to newAddr. Use OneWire::reset_search() to 337 | // start over. 338 | // 339 | // --- Replaced by the one from the Dallas Semiconductor web site --- 340 | //-------------------------------------------------------------------------- 341 | // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing 342 | // search state. 343 | // Return TRUE : device found, ROM number in ROM_NO buffer 344 | // FALSE : device not found, end of search 345 | // 346 | uint8_t OneWire::search(uint8_t *newAddr) 347 | { 348 | uint8_t id_bit_number; 349 | uint8_t last_zero, rom_byte_number, search_result; 350 | uint8_t id_bit, cmp_id_bit; 351 | 352 | unsigned char rom_byte_mask, search_direction; 353 | 354 | // initialize for search 355 | id_bit_number = 1; 356 | last_zero = 0; 357 | rom_byte_number = 0; 358 | rom_byte_mask = 1; 359 | search_result = 0; 360 | 361 | // if the last call was not the last one 362 | if (!LastDeviceFlag) 363 | { 364 | // 1-Wire reset 365 | if (!reset()) 366 | { 367 | // reset the search 368 | LastDiscrepancy = 0; 369 | LastDeviceFlag = FALSE; 370 | LastFamilyDiscrepancy = 0; 371 | return FALSE; 372 | } 373 | 374 | // issue the search command 375 | write(0xF0); 376 | 377 | // loop to do the search 378 | do 379 | { 380 | // read a bit and its complement 381 | id_bit = read_bit(); 382 | cmp_id_bit = read_bit(); 383 | 384 | // check for no devices on 1-wire 385 | if ((id_bit == 1) && (cmp_id_bit == 1)) 386 | break; 387 | else 388 | { 389 | // all devices coupled have 0 or 1 390 | if (id_bit != cmp_id_bit) 391 | search_direction = id_bit; // bit write value for search 392 | else 393 | { 394 | // if this discrepancy if before the Last Discrepancy 395 | // on a previous next then pick the same as last time 396 | if (id_bit_number < LastDiscrepancy) 397 | search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0); 398 | else 399 | // if equal to last pick 1, if not then pick 0 400 | search_direction = (id_bit_number == LastDiscrepancy); 401 | 402 | // if 0 was picked then record its position in LastZero 403 | if (search_direction == 0) 404 | { 405 | last_zero = id_bit_number; 406 | 407 | // check for Last discrepancy in family 408 | if (last_zero < 9) 409 | LastFamilyDiscrepancy = last_zero; 410 | } 411 | } 412 | 413 | // set or clear the bit in the ROM byte rom_byte_number 414 | // with mask rom_byte_mask 415 | if (search_direction == 1) 416 | ROM_NO[rom_byte_number] |= rom_byte_mask; 417 | else 418 | ROM_NO[rom_byte_number] &= ~rom_byte_mask; 419 | 420 | // serial number search direction write bit 421 | write_bit(search_direction); 422 | 423 | // increment the byte counter id_bit_number 424 | // and shift the mask rom_byte_mask 425 | id_bit_number++; 426 | rom_byte_mask <<= 1; 427 | 428 | // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask 429 | if (rom_byte_mask == 0) 430 | { 431 | rom_byte_number++; 432 | rom_byte_mask = 1; 433 | } 434 | } 435 | } 436 | while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 437 | 438 | // if the search was successful then 439 | if (!(id_bit_number < 65)) 440 | { 441 | // search successful so set LastDiscrepancy,LastDeviceFlag,search_result 442 | LastDiscrepancy = last_zero; 443 | 444 | // check for last device 445 | if (LastDiscrepancy == 0) 446 | LastDeviceFlag = TRUE; 447 | 448 | search_result = TRUE; 449 | } 450 | } 451 | 452 | // if no device found then reset counters so next 'search' will be like a first 453 | if (!search_result || !ROM_NO[0]) 454 | { 455 | LastDiscrepancy = 0; 456 | LastDeviceFlag = FALSE; 457 | LastFamilyDiscrepancy = 0; 458 | search_result = FALSE; 459 | } 460 | for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i]; 461 | return search_result; 462 | } 463 | 464 | #endif 465 | 466 | #if ONEWIRE_CRC 467 | // The 1-Wire CRC scheme is described in Maxim Application Note 27: 468 | // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products" 469 | // 470 | 471 | #if ONEWIRE_CRC8_TABLE 472 | // This table comes from Dallas sample code where it is freely reusable, 473 | // though Copyright (C) 2000 Dallas Semiconductor Corporation 474 | static const uint8_t PROGMEM dscrc_table[] = { 475 | 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, 476 | 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, 477 | 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, 478 | 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, 479 | 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, 480 | 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, 481 | 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, 482 | 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, 483 | 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, 484 | 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, 485 | 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, 486 | 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, 487 | 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, 488 | 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, 489 | 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, 490 | 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; 491 | 492 | // 493 | // Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM 494 | // and the registers. (note: this might better be done without to 495 | // table, it would probably be smaller and certainly fast enough 496 | // compared to all those delayMicrosecond() calls. But I got 497 | // confused, so I use this table from the examples.) 498 | // 499 | uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) 500 | { 501 | uint8_t crc = 0; 502 | 503 | while (len--) { 504 | crc = pgm_read_byte(dscrc_table + (crc ^ *addr++)); 505 | } 506 | return crc; 507 | } 508 | #else 509 | // 510 | // Compute a Dallas Semiconductor 8 bit CRC directly. 511 | // this is much slower, but much smaller, than the lookup table. 512 | // 513 | uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) 514 | { 515 | uint8_t crc = 0; 516 | 517 | while (len--) { 518 | uint8_t inbyte = *addr++; 519 | for (uint8_t i = 8; i; i--) { 520 | uint8_t mix = (crc ^ inbyte) & 0x01; 521 | crc >>= 1; 522 | if (mix) crc ^= 0x8C; 523 | inbyte >>= 1; 524 | } 525 | } 526 | return crc; 527 | } 528 | #endif 529 | 530 | #if ONEWIRE_CRC16 531 | bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc) 532 | { 533 | crc = ~crc16(input, len, crc); 534 | return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1]; 535 | } 536 | 537 | uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc) 538 | { 539 | static const uint8_t oddparity[16] = 540 | { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; 541 | 542 | for (uint16_t i = 0 ; i < len ; i++) { 543 | // Even though we're just copying a byte from the input, 544 | // we'll be doing 16-bit computation with it. 545 | uint16_t cdata = input[i]; 546 | cdata = (cdata ^ crc) & 0xff; 547 | crc >>= 8; 548 | 549 | if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4]) 550 | crc ^= 0xC001; 551 | 552 | cdata <<= 6; 553 | crc ^= cdata; 554 | cdata <<= 1; 555 | crc ^= cdata; 556 | } 557 | return crc; 558 | } 559 | #endif 560 | 561 | #endif 562 | --------------------------------------------------------------------------------