Les broches SDA et SCl n’étant pas accessibles simplement, elle sont redéfinies sur GP0 et GP1 (respectivemenent PCB pins 3 et 4).
L’tilisation d’autre PINs reste possible mais les PINs recommendées sont 0, 1, 2, 3, 14, 20, 21, 22, 23, ls autres étant utilisées par BOOT, JTAG, FLASH … et donc posent problèmes.
ESP32S WROOM 30 pins | AHT20-BMP280 |
---|---|
GPIO/D 1 | SDA |
GPIO/D 0 | SCL |
GND | GND |
3.3 Volts |
ATTENTION: les PINs SDA et SCL ont abolument besoin d’une résistance de PullUp (entre 4.7 et 10 kohms) qui les raccordent au +3,3 volts, sans cela, le bus sera instable lors des transitions d’état.
Le firmware de l’ESP-C6 est écrit sur base de la bibliothèque zigbee (Arduino IDE core).
Connexion sur une instance zigbee2mqtt.
Les données de Température et humidité sont bien reçues et envoyée sur le boker mqtt.
#include "config.h"
AHT20 aht;
Adafruit_AHTX0 aht0;
Adafruit_BMP280 bmp;
extern Stream *console;
extern volatile int count;
extern volatile int rcount;
int previous=0;
ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER);
ZigbeePressureSensor zbPressureSensor = ZigbeePressureSensor(PRESSURE_SENSOR_ENDPOINT_NUMBER);
//ZigbeeWindSpeedSensor zbWindSpeedSensor = ZigbeeWindSpeedSensor(WIND_SPEED_SENSOR_ENDPOINT_NUMBER);
ZigbeeAnalog zbAnalogDevice = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER);
ZigbeeAnalog zbWindSpeedSensor = ZigbeeAnalog(WIND_SPEED_SENSOR_ENDPOINT_NUMBER);
uint8_t button = BOOT_PIN;
unsigned long windinstant_t=0;
unsigned long wind_avg_t=0;
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(115200);
unsigned long startTime = millis();
while (!Serial && millis() - startTime < 3000) {
// Wait for up to 5 seconds for a serial connection
// Adjust the timeout value (5000 milliseconds in this case) as needed
}
console = &Serial;
pinMode(button, INPUT_PULLUP);
Serial.println("Started serial");
Serial.println(DEVICE);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
//pinMode(SDA, INPUT_PULLUP);
//pinMode(SCL, INPUT_PULLUP);
Wire.begin(SDA,SCL);
Serial.println("\nI2C Scanner");
scanDevices(&Wire);
if (aht0.begin() == false) {
console->println("AHT20 not detected");
} else {
console->println("Found AHT20");
}
bmp.begin(0x77);
setwind();
setrain();
leds[0] = CRGB::Green; //RGB LED RED whe starting
FastLED.setBrightness(BRIGHTNESS);
FastLED.show();
zbTempSensor.setManufacturerAndModel("ON4KCH", "ZigbeeMeteoStation");
zbTempSensor.addOTAClient(OTA_UPGRADE_RUNNING_FILE_VERSION, OTA_UPGRADE_DOWNLOADED_FILE_VERSION, OTA_UPGRADE_HW_VERSION);
zbTempSensor.setMinMaxValue(10, 50);
zbTempSensor.setTolerance(1);
zbTempSensor.addHumiditySensor(0, 100, 1);
// Optional: Time cluster configuration (default params, as this device will revieve time from coordinator)
zbTempSensor.addTimeCluster();
//zbPressureSensor.setMinMaxValue(0, 10000);
//zbPressureSensor.setTolerance(1);
// Set up analog input
zbAnalogDevice.addAnalogInput();
// second analog input gust
zbWindSpeedSensor.addAnalogInput();
//zbAnalogDevice.setAnalogInputApplication(ESP_ZB_ZCL_AI_RPM_OTHER);
// Add endpoint to Zigbee Core
Zigbee.addEndpoint(&zbWindSpeedSensor);
// Add endpoint to Zigbee Core
Zigbee.addEndpoint(&zbTempSensor);
Zigbee.addEndpoint(&zbPressureSensor);
//Zigbee.addEndpoint(&zbWindSpeedSensor);
Zigbee.addEndpoint(&zbAnalogDevice);
Serial.println("Starting Zigbee...");
// When all EPs are registered, start Zigbee in End Device mode
if (!Zigbee.begin()) {
Serial.println("Zigbee failed to start!");
Serial.println("Rebooting...");
ESP.restart();
} else {
Serial.println("Zigbee started successfully!");
}
Serial.println("Connecting to network");
while (!Zigbee.connected()) {
Serial.print(".");
delay(100);
}
leds[0] = CRGB::Red;
FastLED.show();
digitalWrite(LED_BUILTIN, LOW); //set RGB to green indicate zigbee network connected
// Set reporting interval for windspeed measurement in seconds, must be called after Zigbee.begin()
// min_interval and max_interval in seconds, delta (WindSpeed change in m/s)
// if min = 1 and max = 0, reporting is sent only when windspeed changes by delta
// if min = 0 and max = 10, reporting is sent every 10 seconds or windspeed changes by delta
// if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of windspeed change
zbPressureSensor.setReporting(0, 600, 1);
zbTempSensor.setReporting(0,300,0);
zbAnalogDevice.setAnalogInputReporting(0,600,1);
zbWindSpeedSensor.setAnalogInputReporting(0, 600, 1);
// Start Zigbee OTA client query, first request is within a minute and the next requests are sent every hour automatically
zbTempSensor.requestOTAUpdate();
}
void mesure( measure &val) {
// Measure sensor values
thp(val);
// Update temperature and humidity values in Temperature sensor EP
if (val.temperature > -20) {zbTempSensor.setTemperature(val.temperature);}
if (val.humidity > 0) {zbTempSensor.setHumidity(val.humidity);}
if (val.pressure > 80) {zbPressureSensor.setPressure(int(val.pressure));}
// Report temperature and humidity values
zbTempSensor.report();
Serial.printf("Reported temperature: %.2f°C, Humidity: %.2f%%\r\n", val.temperature, val.humidity);
zbPressureSensor.report();
Serial.printf("Reported pressure: %.2f°mBar\r\n", val.pressure);
zbAnalogDevice.setAnalogInput(val.avgspeed);
Serial.printf("Reported gust wind speed (km/hr): %6.2f\r\n", val.gust);
zbWindSpeedSensor.setAnalogInput(val.gust);
zbWindSpeedSensor.reportAnalogInput();
Serial.printf("Reported avg wind speed (km/hr): %6.2f\r\n", val.avgspeed);
zbAnalogDevice.reportAnalogInput();
// Add small delay to allow the data to be sent before going to sleep
delay(100);
}
void loop() {
if (digitalRead(button) == LOW) { // Push button pressed
// Key debounce handling
delay(100);
int startTime = millis();
while (digitalRead(button) == LOW) {
delay(50);
if ((millis() - startTime) > 10000) {
// If key pressed for more than 10secs, factory reset Zigbee and reboot
Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
delay(1000);
// Optional set reset in factoryReset to false, to not restart device after erasing nvram, but set it to endless sleep manually instead
Zigbee.factoryReset(false);
Serial.println("Going to endless sleep, press RESET button or power off/on the device to wake up");
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
esp_deep_sleep_start();
}
}
}
measure val;
int hits;
// take a measure from sensor and report to zigbee
mesure(val);
char retval[256];
windinstant_t = millis();
wind_avg_t = millis();
val.hitcnt=1; // # of interval for wind average calculation
while (true) {
unsigned long now = millis();
// compute instant speed over the WIND_INSTANT inerval
// store the result in val mesure structure
if ((now - windinstant_t) >= WIND_INSTANT ) {
console->print("Counted: ");
console->println(hits);
// calculate and store "instant speed"
val.speed = Speed();
float factor = float(val.hitcnt - 1)/val.hitcnt;
float temp = val.avgspeed * factor;
//sprintf(retval,"Interval: %d\tFactor %6.2f\tAVG*factor %6.2f\tlast speed %6.2f \tavg speed %6.2f\n", val.hitcnt, factor, temp, val.speed, val.avgspeed);
//console->println(retval);
val.avgspeed = temp + (val.speed / val.hitcnt);
zbAnalogDevice.setAnalogInput(val.avgspeed);
float pluie = rain();
int tilted = rcount;
sprintf(retval,"Interval: %d\tlast speed %6.2f \tavg speed %6.2f\t tilted: %d \tRAIN: %6.2f\n", val.hitcnt, val.speed, val.avgspeed,tilted,pluie);
console->println(retval);
if (val.hitcnt >= 6) {
val.hitcnt = 1;
val.gust = val.speed;
} else {
val.hitcnt += 1;
if ( val.speed > val.gust ){
val.gust = val.speed;
}
}
previous = hits;
windinstant_t = now;
} else if ( (now - wind_avg_t) >= WIND_AVG) {
console->println("Value read from sensors");
mesure(val);
sprintf(retval,"AHT20 - Temp: %6.2f °C Humidity: %d %%\tBMP280 - Temp: %6.2f °C Pressure: %7.2f hPa\tlast speed %6.2f \tavg speed %6.2f\n",val.temperature, val.humidity,val.temperature2, val.pressure, val.speed, val.avgspeed);
console->println(retval);
wind_avg_t = now;
}
if (Serial.available() > 0 ) {
String comd = Serial.readString();
if (comd.startsWith("scan")) {
scanDevices(&Wire);
} else if (comd.startsWith("read")) {
thp(val);
} else if (comd.startsWith("raz")) {
ESP.restart();
} else if (comd.startsWith("who")) {
console->println(DEVICE);
}
console->println(comd);
}
}
delay(10000);
}
#include "config.h"
Stream *console;
uint32_t deviceOnline = 0x00;
extern AHT20 aht;
extern Adafruit_AHTX0 aht0;
extern Adafruit_BMP280 bmp;
volatile int count = 0;
volatile int rcount = 0; //amount of bucket tips.
//const byte interruptPin = INTERRUPT;
const byte rinterruptPin = RAININTRPT;
enum {
POWERMANAGE_ONLINE = _BV(0),
DISPLAY_ONLINE = _BV(1),
RADIO_ONLINE = _BV(2),
GPS_ONLINE = _BV(3),
PSRAM_ONLINE = _BV(4),
SDCARD_ONLINE = _BV(5),
AXDL345_ONLINE = _BV(6),
BME280_ONLINE = _BV(7),
BMP280_ONLINE = _BV(8),
BME680_ONLINE = _BV(9),
QMC6310_ONLINE = _BV(10),
QMI8658_ONLINE = _BV(11),
PCF8563_ONLINE = _BV(12),
OSC32768_ONLINE = _BV(13),
};
void scanDevices(TwoWire *w)
{
uint8_t err, addr;
int nDevices = 0;
uint32_t start = 0;
console->println("I2C Devices scanning");
for (addr = 1; addr < 127; addr++) {
start = millis();
w->beginTransmission(addr); delay(2);
err = w->endTransmission();
if (err == 0) {
nDevices++;
switch (addr) {
case 0x77:
case 0x76:
console->println("\tFind BMX280 Sensor!");
deviceOnline |= BME280_ONLINE;
break;
case 0x34:
console->println("\tFind AXP192/AXP2101 PMU!");
deviceOnline |= POWERMANAGE_ONLINE;
break;
case 0x3C:
console->println("\tFind SSD1306/SH1106 dispaly!");
deviceOnline |= DISPLAY_ONLINE;
break;
case 0x51:
console->println("\tFind PCF8563 RTC!");
deviceOnline |= PCF8563_ONLINE;
break;
case 0x1C:
console->println("\tFind QMC6310 MAG Sensor!");
deviceOnline |= QMC6310_ONLINE;
break;
default:
console->print("\tI2C device found at address 0x");
if (addr < 16) {
console->print("0");
}
console->print(addr, HEX);
console->println(" !");
break;
}
} else if (err == 4) {
console->print("Unknow error at address 0x");
if (addr < 16) {
console->print("0");
}
console->println(addr, HEX);
}
}
if (nDevices == 0)
console->println("No I2C devices found\n");
console->println("Scan devices done.");
console->println("\n");
}
void thp( measure &val){
/*
return a structure with measured values from the sensors
REQUIRES initialization of I2C devices:
AHT20 aht;
Adafruit_BMP280 bmp;
*/
sensors_event_t humidity, temp;
aht0.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
console->print("Getting data from AHT20\t");
val.temperature = temp.temperature; //aht.getTemperature();
val.humidity = humidity.relative_humidity; //aht.getHumidity();
console->println(val.temperature);
console->print("Getting data from BMP\t");
val.pressure = bmp.readPressure() / 100.0;
val.temperature2=bmp.readTemperature();
console->print(val.temperature2);
console->print("\t");
console->println(val.pressure);
console->print("Getting data from count\t");
val.hit= float(count);
console->println(val.hit);
}
void IRAM_ATTR counter() {
static unsigned long last_micros = 0;
unsigned long interrupt_time = millis();
if ( interrupt_time - last_micros > 50UL ) {
count += 1; // increment count
}
last_micros = interrupt_time;
}
void IRAM_ATTR countRain() {
static unsigned long last_micros = 0;
unsigned long interrupt_time = millis();
console->print(".");
if ( interrupt_time - last_micros > 50UL ) {
rcount += 1; // increment count
}
last_micros = interrupt_time;
}
float Speed() {
/*
calculate the linear speed from magnets hit count, the routine gets called when average timer lapse (thus after measureperiod ms).
REQUIRES:
count: number of magnet detection
measureperiod: averaging period for rotational counts (ms)
RADIUS= distance between HAL detector and rotation axis centre.
PRVIDES:
sets global variable float speed
*/
noInterrupts();
int interval = WIND_INSTANT / 1000; //anemometer averaging interval (sec)
char text[128]; //text buffer for sprintf
int local = count;
float speed;
float RPM;
int tour = local / 4; //3 magnets, it takes 4 hits to detect a full 360°
//speed = 3.1415926 * 2 * float(tour) * RADIUS / float(interval) ;
RPM = float(local) * ( 60 / interval); // tour/minutes
speed = RPM * RADIUS * 60 * 3.1415926 * 2. / 1000.; // vitesse radiale km/hr = vitesse angulaire (rad/min) * 2 Pi * rayon (m) * 60 (min/hr) / 1000 (m/km)
if (local > 0) {
sprintf(text," Speed calculation: Count %d \tRPM %8.2f (T/min)\tspeed %8.4f (km/hr) ", local, RPM, speed);
console->println(text);
}
count=0;
interrupts();
return speed;
}
float rain(){
/* rain fall is amount of water that fell down in 24 hours at 8:30 in the morning */
noInterrupts();
int local = rcount;
float millis = 0.550053 * local;
console->println(local);
interrupts();
return millis;
}
void setwind(){
/* et the interrupt mechanism that intercept the magnet detection and accumulates its counting */
pinMode(INTERRUPT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(INTERRUPT), counter, RISING);
//timermeasure.set(measureperiod, Speed);
//TTNuplink.set(ttnuplinkperiod, TTNsend);
}
void setrain() {
console->print("setting rain interupt pin :");
console->println(RAININTRPT);
pinMode(RAININTRPT,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RAININTRPT), countRain, RISING);
}
#include <Wire.h>
#include <AHT20.h>
#include <Adafruit_BMP280.h>
#include <FastLED.h>
#include <Adafruit_AHTX0.h>
#define DEVICE "ESP32-C6-Zero"
#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif
#include "Zigbee.h"
#define LED_BUILTIN 13 //blue LED user conrolable
#define RGB_LED 8 //controlable RGB LED
#define NUM_LEDS 1
#define DATA_PIN 8
#define BRIGHTNESS 16
/* Zigbee OTA configuration */
#define OTA_UPGRADE_RUNNING_FILE_VERSION 0x01010100 // Increment this value when the running image is updated
#define OTA_UPGRADE_DOWNLOADED_FILE_VERSION 0x01010101 // Increment this value when the downloaded image is updated
#define OTA_UPGRADE_HW_VERSION 0x0101 // The hardware version, this can be used to differentiate between different hardware versions
/* Zigbee temperature sensor configuration */
#define TEMP_SENSOR_ENDPOINT_NUMBER 10
#define PRESSURE_SENSOR_ENDPOINT_NUMBER 11
#define ANALOG_DEVICE_ENDPOINT_NUMBER 12
#define WIND_SPEED_SENSOR_ENDPOINT_NUMBER 9
#define RADIUS 0.028 // 28 mm de rayon
#define AVGINTERVALS 6 //# of intervale for average speed should be WIND_AVG / WIND_INSTATNT
#define WIND_INSTANT 5000UL //intervale to compute the instant speed 5000 ms
#define WIND_AVG 30000UL // reporting interval 30 sec
#define SCL 1
#define SDA 0
#define INTERRUPT 3
#define RAININTRPT 5
typedef struct {
float temperature;
float temperature2;
float pressure;
int humidity;
float hit;
float speed;
float gust;
int hitcnt; // number of intervals used in wind average calculation
float avgspeed; // average speed
}
measure;
void scanDevices(TwoWire *w);
void thp( measure &val);
void setwind();
void setrain();
void IRAM_ATTR counter();
float Speed();
float rain();
void IRAM_ATTR countRain();