// для работы с ESP-32 // target Arduino UNO #include "LowPower.h" #include "Wire.h" #include "SparkFunLIS3DH.h" LIS3DH IMU1(I2C_MODE, 0x19); //Default constructor is I2C, addr 0x19. //#include //AsyncStream<16> serial(&Serial, '~'); const int ESP_RESET_PIN = 5; // OLD - 2 const int ESP_READY_PIN = 3; const int ESP_CFG_PIN = 4; // OLD - 5 const int LED_4BLINK = 6; #define ACCSEL_READ_PERIOD 100 // частота опроса акселя в миллисекундах #define ESP_WAIT_LIMIT 500 // максимальное время ожидания пробуждения ESP32 #define ESP_READY_DURATION 25 // длительность сигнала "готов" ESP32 uint32_t sec; uint32_t steps = 0; bool blinkmode = false; void wakeUp() { // Just a handler for the pin interrupt. } int int_loops_cnt = 0; #define LOOPS_CNT_AFTER_INT2 15 void setup() { delay(100); // а то похоже из-за кондёров по 10мкФ на стабилизаторе аксель не успевает запуститьсы до проверки контроллером при первом включении. Serial.begin(115200); //Serial.begin(57600); //Serial.begin(19200); //Serial.begin(9600); //Serial.begin(2400); //Serial.println("LSM6DS3 Basic Reading Code!"); Wire.begin(); pinMode(ESP_READY_PIN, INPUT); pinMode(ESP_RESET_PIN, OUTPUT); //pinMode(ESP_INFO_PIN, OUTPUT); pinMode(ESP_CFG_PIN, OUTPUT); analogReference(INTERNAL); // встроенный источник опорного на 1.1V (для ATmega168 или ATmega328P) и 2.56V (на ATmega8) digitalWrite(ESP_RESET_PIN, LOW); // IMU 1 - LSM6DS3 IMU1.settings.accelSampleRate = 10; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz IMU1.settings.accelRange = 2; //Max G force readable. Can be: 2, 4, 8, 16 IMU1.settings.xAccelEnabled = 1; IMU1.settings.yAccelEnabled = 1; IMU1.settings.zAccelEnabled = 1; IMU1.settings.adcEnabled = 0; IMU1.settings.tempEnabled = 0; //Call .begin() to configure the IMU //digitalWrite(ESP_CFG_PIN, HIGH); if (IMU1.begin() != IMU_SUCCESS) { //Serial.println("Not Connected. Please check connections and read the hookup guide."); blinkmode=true; pinMode(LED_4BLINK, OUTPUT); //digitalWrite(ESP_RESET_PIN, LOW); //delay(50); //digitalWrite(ESP_RESET_PIN, HIGH); digitalWrite(ESP_CFG_PIN, HIGH); delay(50); }else{ configIntterupts(); } delay(ACCSEL_READ_PERIOD); sec = millis(); } #define LOOPS_LIMIT 10 int16_t accel_buf[LOOPS_LIMIT * 3]; int loopnum = 0; void getAccelData() { //Serial.println(loopnum); if (loopnum >= LOOPS_LIMIT) {return;} accel_buf[loopnum * 3] = IMU1.readRawAccelX(); accel_buf[loopnum * 3 + 1] = IMU1.readRawAccelY(); accel_buf[loopnum * 3 + 2] = IMU1.readRawAccelZ(); loopnum++; return; } uint32_t tm_esp_fin = 0, esp_wait_time = 0; void loop() { if(blinkmode){ digitalWrite(LED_4BLINK, HIGH); delay(500); digitalWrite(LED_4BLINK, LOW); delay(500); return; } if(int_loops_cnt >= LOOPS_CNT_AFTER_INT2){ // Allow wake up pin to trigger interrupt on high. attachInterrupt(0, wakeUp, HIGH); // Enter power down state with ADC and BOD module disabled. // Wake up when wake up pin is high. LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // Disable external pin interrupt on wake up pin. detachInterrupt(0); int_loops_cnt = 0; //digitalWrite(LED_4BLINK, HIGH); sec = millis(); digitalWrite(ESP_RESET_PIN, HIGH); // это не ресет. Для ESP-32 даём на заданую ногу сигнал пробуждения delay(10); digitalWrite(ESP_RESET_PIN, LOW); } getAccelData(); if (loopnum >= LOOPS_LIMIT) { digitalWrite(LED_4BLINK, HIGH); // output data // blink LOW for restert ESP-01 digitalWrite(ESP_CFG_PIN, LOW); //delay(50); if(esp_wait_time == 0) {esp_wait_time = millis();} uint32_t tmp_time = millis(); // wait ESP led ON bool esp_ready = false; while ((digitalRead(ESP_READY_PIN) == LOW) && ((millis()-esp_wait_time) < ESP_WAIT_LIMIT)) {delay(1);} //while (digitalRead(ESP_READY_PIN) == LOW) {delay(1);} if (digitalRead(ESP_READY_PIN) == HIGH){ uint32_t led_on_time = millis(); //while ((digitalRead(ESP_READY_PIN) == HIGH) && ((millis()-led_on_time) < ESP_READY_DURATION)) {delay(1);} //if ((millis()-led_on_time) >= ESP_READY_DURATION) {esp_ready = true;} } if (esp_ready){ loopnum = 0; // NON STOP VERSION //int_loops_cnt++; // delay(95); digitalWrite(ESP_RESET_PIN, LOW); digitalWrite(LED_4BLINK, HIGH); //digitalWrite(ESP_INFO_PIN, HIGH); // send data to ESP //uint32_t sec_start = millis(); steps++; if(int_loops_cnt >= LOOPS_CNT_AFTER_INT2){ Serial.print("L/"); // send last loop flag } Serial.print("Start step "); Serial.print(int_loops_cnt); Serial.print("/"); Serial.print(steps); Serial.print(" / "); Serial.print(String(tm_esp_fin) + "/" + String(millis())); Serial.print(" / ESP wait time "+String(esp_wait_time)+"/"); Serial.print(millis()-esp_wait_time); Serial.print(" / bat.volt. "); Serial.println(voltmeter(), 2); //Serial.println(); //Serial.println("============================================="); for (int i = 0; i < LOOPS_LIMIT; i++) { String ds = String(i) + ","; // print IMU 1 data / plotter format ds += String(accel_buf[i * 3]); ds += ","; ds += String(accel_buf[i * 3 + 1]); ds += ","; ds += String(accel_buf[i * 3 + 2]); if (i < (LOOPS_LIMIT - 1)) ds += ";"; Serial.print(ds); //Serial.println(ds); //if ((millis() - tmp_time) > ACCSEL_READ_PERIOD) { // tmp_time = millis(); // //getAccelData(); //} } Serial.println("~"); digitalWrite(LED_4BLINK, LOW); tm_esp_fin = millis(); esp_wait_time = 0; }else{ for(int nblink=0; nblink < 3; nblink++){ digitalWrite(ESP_RESET_PIN, HIGH); // это не ресет. Для ESP-32 даём на заданую ногу сигнал пробуждения digitalWrite(LED_4BLINK, HIGH); delay(50); digitalWrite(ESP_RESET_PIN, LOW); digitalWrite(LED_4BLINK, LOW); delay(50); } } } uint32_t sec_delta = (millis() - sec) % ACCSEL_READ_PERIOD; delay(ACCSEL_READ_PERIOD - sec_delta); //digitalWrite(LED_4BLINK, LOW); } #define VOLTMETER_PIN A3 #define VOLTMETER_BASE 1.1 // встроенный источник опорного 1.1V (для ATmega168 или ATmega328P) и 2.56V (на ATmega8) #define VOLTMETER_CALIBR 1 float input_volt = 0.0; float temp = 0.0; float r1 = 100000.0; //сопротивление резистора r1 float r2 = 10000.0; // сопротивление резистора r2 float voltmeter() { int analogvalue = analogRead(VOLTMETER_PIN); temp = (analogvalue * VOLTMETER_BASE) / 1024.0; // формула для конвертирования значения напряжения input_volt = temp / (r2 / (r1 + r2)) * VOLTMETER_CALIBR; if (input_volt < 0.1) input_volt = 0.0; return (input_volt); } void configIntterupts() { uint8_t dataToWrite = 0; //LIS3DH_CLICK_CFG dataToWrite = 0; //Set these to enable individual axes of generation source (or direction) // -- set = 1 to enable dataToWrite |= 0x10;//Z click dataToWrite |= 0x04;//Y click dataToWrite |= 0x01;//X click IMU1.writeRegister(LIS3DH_CLICK_CFG, dataToWrite); //LIS3DH_CLICK_SRC dataToWrite = 0; //Set these to enable click behaviors (also read to check status) // -- set = 1 to enable dataToWrite |= 0x10;//Enable single clicks //dataToWrite |= 0x08;//sine (0 is positive, 1 is negative) dataToWrite |= 0x04;//Z click detect enabled dataToWrite |= 0x02;//Y click detect enabled dataToWrite |= 0x01;//X click detect enabled IMU1.writeRegister(LIS3DH_CLICK_SRC, dataToWrite); //LIS3DH_CLICK_THS dataToWrite = 0; //This sets the threshold where the click detection process is activated. //Provide 7 bit value, 0x7F always equals max range by accelRange setting //dataToWrite |= 0x0A; // ~1/16 range dataToWrite |= 0x05; // ~1/16 range IMU1.writeRegister(LIS3DH_CLICK_THS, dataToWrite); //LIS3DH_TIME_LIMIT dataToWrite = 0; //Time acceleration has to fall below threshold for a valid click. //LSB equals 1/(sample rate) dataToWrite |= 0x08; // 8 * 1/50 s = 160ms IMU1.writeRegister(LIS3DH_TIME_LIMIT, dataToWrite); //LIS3DH_TIME_LATENCY dataToWrite = 0; //hold-off time before allowing detection after click event //LSB equals 1/(sample rate) dataToWrite |= 0x08; // 4 * 1/50 s = 160ms IMU1.writeRegister(LIS3DH_TIME_LATENCY, dataToWrite); //LIS3DH_TIME_WINDOW dataToWrite = 0; //hold-off time before allowing detection after click event //LSB equals 1/(sample rate) dataToWrite |= 0x10; // 16 * 1/50 s = 320ms IMU1.writeRegister(LIS3DH_TIME_WINDOW, dataToWrite); //LIS3DH_CTRL_REG5 //Int1 latch interrupt and 4D on int1 (preserve fifo en) IMU1.readRegister(&dataToWrite, LIS3DH_CTRL_REG5); dataToWrite &= 0xF3; //Clear bits of interest dataToWrite |= 0x08; //Latch interrupt (Cleared by reading int1_src) //dataToWrite |= 0x04; //Pipe 4D detection from 6D recognition to int1? IMU1.writeRegister(LIS3DH_CTRL_REG5, dataToWrite); //LIS3DH_CTRL_REG3 //Choose source for pin 1 dataToWrite = 0; // dataToWrite |= 0x40; //AOI1 event (Generator 1 interrupt on pin 1) dataToWrite |= 0x20; //AOI2 event () IMU1.writeRegister(LIS3DH_CTRL_REG3, dataToWrite); //LIS3DH_CTRL_REG6 //Choose source for pin 2 and both pin output inversion state dataToWrite = 0; dataToWrite |= 0x80; //Click int on pin 2 IMU1.writeRegister(LIS3DH_CTRL_REG6, dataToWrite); }