Commit 468f7039 authored by Jochen Rößner's avatar Jochen Rößner
Browse files

first rework to esp32

parent c0a521fa
cmake_minimum_required(VERSION 3.16.0)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(espidf-arduino-ulp-simple)
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x150000,
app1, app, ota_1, 0x160000,0x150000,
spiffs, data, spiffs, 0x2B0000,0x150000,
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
#include <Arduino.h>
#include <limits.h>
unsigned long crc(uint8_t* blob,unsigned int size);
#include "Arduino.h"
extern uint32_t ulp_entry;
extern uint32_t ulp_led_delay;
//extern uint32_t ulp_low_thr;
extern uint32_t ulp_high_thr;
extern uint32_t ulp_sample_counter;
extern uint32_t ulp_last_result_rx;
extern uint32_t ulp_last_result_tx;
extern uint32_t ulp_last_result_diff;
......@@ -7,21 +7,26 @@
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp12e]
platform = espressif8266
board = d1_mini
framework = arduino
; build_flags = -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
[env:esp32dev]
platform = espressif32
;board_upload.maximum_size = 4194304
framework = arduino, espidf
;board = featheresp32
board = esp32dev
;board = esp-wrover-kit
board_build.partitions = custom_small_spiffs.csv
build_flags =
-DCORE_DEBUG_LEVEL=4
!sh build_timestamp.sh
-D ESP32
; build_flags = -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
; Custom Serial Monitor port
monitor_port = /dev/ttyUSB0
; Custom Serial Monitor speed (baud rate)
monitor_speed = 74880
platform_packages =
; use a special branch
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#idf-release/v4.0
monitor_port = /dev/ttyUSB0
monitor_speed = 115200
upload_port = /dev/ttyUSB0
......
This diff is collapsed.
# Override some defaults to enable Arduino framework
CONFIG_ENABLE_ARDUINO_DEPENDS=y
CONFIG_AUTOSTART_ARDUINO=y
CONFIG_ARDUINO_RUN_CORE1=y
CONFIG_ARDUINO_RUNNING_CORE=1
CONFIG_ARDUINO_EVENT_RUN_CORE1=y
CONFIG_ARDUINO_EVENT_RUNNING_CORE=1
CONFIG_ARDUINO_UDP_RUN_CORE1=y
CONFIG_ARDUINO_UDP_RUNNING_CORE=1
CONFIG_DISABLE_HAL_LOCKS=y
CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_ERROR=y
CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL=1
CONFIG_ARDUHAL_PARTITION_SCHEME_DEFAULT=y
CONFIG_ARDUHAL_PARTITION_SCHEME="default"
CONFIG_AUTOCONNECT_WIFI=y
CONFIG_ARDUINO_SELECTIVE_WiFi=y
CONFIG_MBEDTLS_PSK_MODES=y
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
# Enable ULP
CONFIG_ESP32_ULP_COPROC_ENABLED=y
CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=1024
\ No newline at end of file
#idf_component_register(SRCS "main.cpp")
idf_component_register(SRCS "main.cpp" "crc.cpp" "app.cpp" INCLUDE_DIRS "../lib" "../include" ".")
#
# ULP support additions to component CMakeLists.txt.
#
# 1. The ULP app name must be unique (if multiple components use ULP).
set(ulp_app_name ulp_main)
#
# 2. Specify all assembly source files.
# Files should be placed into a separate directory (in this case, ulp/),
# which should not be added to COMPONENT_SRCS.
set(ulp_s_sources "../ulp/ulp.S")
#
# 3. List all the component source files which include automatically
# generated ULP export file, ${ulp_app_name}.h:
set(ulp_exp_dep_srcs "main.c")
#
# 4. Call function to build ULP binary and embed in project using the argument
# values above.
ulp_embed_binary(${ulp_app_name} ${ulp_s_sources} ${ulp_exp_dep_srcs})
#include <Arduino.h>
#include "config.h"
#include <SimpleDHT.h>
#define SCK_DELAY 1
#include <HX711_ADC.h>
// for DHT11,
// VCC: 5V or 3V
// GND: GND
// DATA: 2
int pinDHT11 = 32;
SimpleDHT11 dht11(pinDHT11);
const int HX711_dout = 34; //mcu > HX711 dout pin
const int HX711_sck = 35; //mcu > HX711 sck pin
//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);
const int calVal_calVal_eepromAdress = 0;
const int calVal_eepromAdress = 0;
unsigned long t = 0;
void calibrate() {
Serial.println("***");
Serial.println("Start calibration:");
Serial.println("Place the load cell an a level stable surface.");
Serial.println("Remove any load applied to the load cell.");
Serial.println("Send 't' from serial monitor to set the tare offset.");
boolean _resume = false;
while (_resume == false) {
LoadCell.update();
if (Serial.available() > 0) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
}
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
_resume = true;
}
}
Serial.println("Now, place your known mass on the loadcell.");
Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");
float known_mass = 0;
_resume = false;
while (_resume == false) {
LoadCell.update();
if (Serial.available() > 0) {
known_mass = Serial.parseFloat();
if (known_mass != 0) {
Serial.print("Known mass is: ");
Serial.println(known_mass);
_resume = true;
}
}
}
LoadCell.refreshDataSet(); //refresh the dataset to be sure that the known mass is measured correct
float newCalibrationValue = LoadCell.getNewCalibration(known_mass); //get the new calibration value
Serial.print("New calibration value has been set to: ");
Serial.print(newCalibrationValue);
Serial.println(", use this as calibration value (calFactor) in your project sketch.");
Serial.print("Save this value to EEPROM adress ");
Serial.print(calVal_eepromAdress);
Serial.println("? y/n");
_resume = false;
while (_resume == false) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
/*
#if defined(ESP8266)|| defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266)|| defined(ESP32)
EEPROM.commit();
#endif
EEPROM.get(calVal_eepromAdress, newCalibrationValue);
*/
Serial.print("Value ");
Serial.print(newCalibrationValue);
Serial.print(" saved to EEPROM address: ");
Serial.println(calVal_eepromAdress);
_resume = true;
}
else if (inByte == 'n') {
Serial.println("Value not saved to EEPROM");
_resume = true;
}
}
}
Serial.println("End calibration");
Serial.println("***");
Serial.println("To re-calibrate, send 'r' from serial monitor.");
Serial.println("For manual edit of the calibration value, send 'c' from serial monitor.");
Serial.println("***");
}
void changeSavedCalFactor() {
float oldCalibrationValue = LoadCell.getCalFactor();
boolean _resume = false;
Serial.println("***");
Serial.print("Current value is: ");
Serial.println(oldCalibrationValue);
Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
float newCalibrationValue;
while (_resume == false) {
if (Serial.available() > 0) {
newCalibrationValue = Serial.parseFloat();
if (newCalibrationValue != 0) {
Serial.print("New calibration value is: ");
Serial.println(newCalibrationValue);
LoadCell.setCalFactor(newCalibrationValue);
_resume = true;
}
}
}
_resume = false;
Serial.print("Save this value to EEPROM adress ");
Serial.print(calVal_eepromAdress);
Serial.println("? y/n");
while (_resume == false) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
/*
#if defined(ESP8266)|| defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266)|| defined(ESP32)
EEPROM.commit();
#endif
EEPROM.get(calVal_eepromAdress, newCalibrationValue);
*/
Serial.print("Value ");
Serial.print(newCalibrationValue);
Serial.print(" saved to EEPROM address: ");
Serial.println(calVal_eepromAdress);
_resume = true;
}
else if (inByte == 'n') {
Serial.println("Value not saved to EEPROM");
_resume = true;
}
}
}
Serial.println("End change calibration value");
Serial.println("***");
}
void app_setup() {
float calibrationValue; // calibration value
calibrationValue = 696.0; // uncomment this if you want to set this value in the sketch
/*
#if defined(ESP8266) || defined(ESP32)
EEPROM.begin(512); // uncomment this if you use ESP8266 and want to fetch this value from eeprom
#endif
EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch this value from eeprom
*/
LoadCell.begin();
unsigned long stabilizingtime = 2000; // tare preciscion can be improved by adding a few seconds of stabilizing time
boolean _tare = true; //set this to false if you don't want tare to be performed in the next step
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
}
else {
LoadCell.setCalFactor(calibrationValue); // set calibration factor (float)
LoadCell.setCalFactor(1.0); // set calibration factor (float)
Serial.println("Startup is complete");
}
while (!LoadCell.update());
Serial.print("Calibration value: ");
Serial.println(LoadCell.getCalFactor());
Serial.print("HX711 measured conversion time ms: ");
Serial.println(LoadCell.getConversionTime());
Serial.print("HX711 measured sampling rate HZ: ");
Serial.println(LoadCell.getSPS());
Serial.print("HX711 measured settlingtime ms: ");
Serial.println(LoadCell.getSettlingTime());
Serial.println("Note that the settling time may increase significantly if you use delay() in your sketch!");
if (LoadCell.getSPS() < 7) {
Serial.println("!!Sampling rate is lower than specification, check MCU>HX711 wiring and pin designations");
}
else if (LoadCell.getSPS() > 100) {
Serial.println("!!Sampling rate is higher than specification, check MCU>HX711 wiring and pin designations");
}
}
void m_loop() {
// start working...
Serial.println("=================================");
Serial.println("Sample DHT11...");
// read without samples.
byte temperature = 0;
byte humidity = 0;
int err = SimpleDHTErrSuccess;
if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
Serial.print("Read DHT11 failed, err="); Serial.print(SimpleDHTErrCode(err));
Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(1000);
return;
}
Serial.print("Sample OK: ");
Serial.print((int)temperature); Serial.print(" *C, ");
Serial.print((int)humidity); Serial.println(" H");
// DHT11 sampling rate is 1HZ.
// delay(1500);
static boolean newDataReady = 0;
const int serialPrintInterval = 500; //increase value to slow down serial print activity
// check for new data/start next conversion:
if (LoadCell.update()) newDataReady = true;
// get smoothed value from the dataset:
if (newDataReady) {
if (millis() > t + serialPrintInterval) {
float i = LoadCell.getData();
Serial.print("Load_cell output val: ");
Serial.println(i);
newDataReady = 0;
t = millis();
}
}
// receive command from serial terminal, send 't' to initiate tare operation:
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
// check if last tare operation is complete:
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}
}
void app_loop() {
static boolean newDataReady = 0;
const int serialPrintInterval = 0; //increase value to slow down serial print activity
// check for new data/start next conversion:
if (LoadCell.update()) newDataReady = true;
// get smoothed value from the dataset:
if (newDataReady) {
if (millis() > t + serialPrintInterval) {
float i = LoadCell.getData();
Serial.print("Load_cell output val: ");
Serial.println(i);
newDataReady = 0;
t = millis();
}
}
// receive command from serial terminal
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay(); //tare
else if (inByte == 'r') calibrate(); //calibrate
else if (inByte == 'c') changeSavedCalFactor(); //edit calibration value manually
}
// check if last tare operation is complete
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}
}
\ No newline at end of file
#include <Arduino.h>
#define DEFAULT_HOSTNAME "regenmesser"
#define CONFIG_CHAR_LENGTH 40
#define POWER_PIN D8
extern const char *version;
extern const char *buildtime;
struct hostConfig
{
IPAddress _ip;
IPAddress _gw;
IPAddress _sn;
char hostName[CONFIG_CHAR_LENGTH];
char realName[CONFIG_CHAR_LENGTH];
unsigned long crc;
};
struct logicDebugPin {
const char *name;
uint8_t pin;
};
#define MAXTOPICLENGTH 128
#define MAXPAYLOADLENGTH 30
#define MAXURLLENGHT 128
/* App configuration */
struct appConfig
{
char mqttTopicprefix[CONFIG_CHAR_LENGTH] = {};
char mqttHost[CONFIG_CHAR_LENGTH] = {};
unsigned int mqttPort = 0;
//float R2_CAL[SENSORCOUNT] = {};
unsigned long crc = 0;
};
#include <Arduino.h>
#include <limits.h>
unsigned long crc(uint8_t* blob,unsigned int size) {
const unsigned long crc_table[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
unsigned long crc = ~0L;
uint8_t* data = (uint8_t*) (blob);
for (unsigned int index = 0 ; index < (size - sizeof(unsigned long) ) ; ++index) {
crc = crc_table[(crc ^ data[index]) & 0x0f] ^ (crc >> 4);
crc = crc_table[(crc ^ (data[index] >> 4)) & 0x0f] ^ (crc >> 4);
crc = ~crc;
}
return crc;
}
This diff is collapsed.
/* ULP assembly files are passed through C preprocessor first, so include directives
and C macros may be used in these files
*/
#include "soc/rtc_cntl_reg.h"
#include "soc/soc_ulp.h"
#include "soc/rtc_io_reg.h" // for RTC_GPIO_*
/* example pins
.set gpio_2, 12 // gpio pin 2 is rtc pin 12
.set gpio_32, 9
.set gpio_25, 6 // gpio pin 32 is rtc pin 9
*/
.set gpio_27, 17
.set gpio_led_rx, gpio_27
.set gpio_13, 14
.set gpio_led_tx, gpio_13
/* ADC1 channel 6, GPIO34 */
.set adc_channel, 6
/* Configure the number of ADC samples to average on each measurement.
For convenience, make it a power of 2. */
.set adc_oversampling_factor_log, 2
.set adc_oversampling_factor, (1 << adc_oversampling_factor_log)
/* Define variables, which go into .bss section (zero-initialized data) */
.bss
.global led_delay
led_delay:
.long 0
/* Low threshold of ADC reading.
Set by the main program. */
/*.global low_thr
low_thr:
.long 0*/
/* High threshold of ADC reading.
Set by the main program. */
.global high_thr
high_thr:
.long 0
/* Counter of measurements done */
.global sample_counter
sample_counter:
.long 0
.global last_result_rx
last_result_rx:
.long 0
.global last_result_tx
last_result_tx:
.long 0
.global last_result_diff
last_result_diff:
.long 0
/* Code goes into .text section */
.text
.global entry
entry:
// might be needed for some pads, but surely not #2
// WRITE_RTC_REG(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_TO_GPIO_S, 1, 1)
//WRITE_RTC_REG(RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_TO_GPIO_S, 1, 1)
// use digital function, not rtc function
// WRITE_RTC_REG(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_S, 1, 1)
WRITE_RTC_REG(RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_MUX_SEL_S, 1, 1)
WRITE_RTC_REG(RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_MUX_SEL_S, 1, 1)
// gpio_* shall be output, not input
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + gpio_led_rx, 1, 1)
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + gpio_led_tx, 1, 1)
/* power on rx led */
WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS_S + gpio_led_rx, 1, 1)
move r1, led_delay // wait in ms
ld r1, r1, 0
move r2, pre_init_adc_rx // return address
jump delay // call delay subroutine
pre_init_adc_rx:
/* increment sample counter */
move r3, sample_counter
ld r2, r3, 0
add r2, r2, 1
st r2, r3, 0
/* do measurements using ADC */
/* r0 will be used as accumulator */
move r0, 0
/* initialize the loop counter */
stage_rst
measure_rx:
/* measure and add value to accumulator */
adc r1, 0, adc_channel + 1
add r0, r0, r1
/* increment loop counter and check exit condition */
stage_inc 1
jumps measure_rx, adc_oversampling_factor, lt
/* divide accumulator by adc_oversampling_factor.
Since it is chosen as a power of two, use right shift */
rsh r0, r0, adc_oversampling_factor_log
/* averaged value is now in r0; store it into last_result */