Wired up the ESP32 to read two thermocouples, Bean Temperature (BT) and Environmental Temperature (ET).
ESP32 als o
Arduino 3.2.2
https://forum.arduino.cc/t/mac-os-update-killed-esp32-sketch/969580/18
go to /users/library/Arduino15/packages/esp32/hardware/esp32/1.0.4
Edit platform.txt
change to python to python3 in esp32part.cmd
tools.gen_esp32part.cmd=python3 "{runtime.platform.path}/tools/gen_esp32part.py"
Problem that took me the longest to fix was I would loss communication between the PC and the ESP32.
I would setup Artisan to display data from the ESP32, either serial usb link or bluetooth, and if I let it run for a while there would be a period of about a minute where no data showed up. Started to use the
I thought it was caused by noise at first, then narrowed it down to software. I used the Help - Serial screen in Artisan to see when it would drop without having to watch it all the time.
Eventually figured out it was a timing problem, ESP32 was running a one second loop and Artisan had a 0.8 sec timeout. Deleted the one second loop, let ESP32 loop as fast as it wants and now now problem.
I was having problems where the ESP32 would reset, blank the display or lose com with Artisan. Eventually realized some problems were related to fan power, some of them would show up when I turned the fan on, or after I lowered power using the dimmer.
At first I rerouted the AC lines away from the ESP32 lines, and that helped, but didn't fix everything.
Later, the boost transformer failed. I removed, and problems were solved. So I think the boost transformer was faulty. When it failed, it got really hot and started to smoke. I removed it, and it didn't lower how much I could roast, so it wasn't helping me anyway.
Initially, ESP32 would reset when I turned the fan on.
Rerouted all the wiring inside, to separate 115V and the logic level wires as much as possible. Also simplified wiring as much as possible, and moved the ESP32 to be closer to front and to 5V regulator, to make ESP32 wires shorter.
Fixed fan reset problem.
But all problems were not fixed until the boost transformer failed, then I removed it.
After I fixed and installed the ZCD Arduino circuit, I started having problems again. Display was blanking out and not coming back. When display did work, it would toggle between auto and manual mode like someone was constantly pushing a button. Lots of noise in the BT and ET readings.
I already cleaned up the AC wiring, and keeping it as separate as I could from the logic level stuff before.
Decided to give the arduino its own power, so I used the transformer for ZCD, added another bridge and cap and 7805, and made a little 5VDC power supply for the arduino.
After this change, it was better. Display stayed on most of the time, but if I toggled fan power enough times I would still lose the display. And still toggled between auto and manual mode.
I added a long piece of about 2" wide copper tape. It was insulated from the case, and I used this to make a ground plane. Tied all grounds into the tape, but I don't know if it really helped, maybe a little better for the display but still auto/manual toggle problem.
Last change was to add a CLC filter at the fan power ac outlet.
Has 1.0 uf and 0.1 uf x caps in parallel , JW Miller 8109 CMC inductor then another set of 1.0 uf and 0.1 uf x caps in parallel
Line from fan switch and neutral connect to one end, other end connects to AC outlet.
After installing this filter, noise problems mostly fixed.
Note that its probably overkill, but I had one around that I wasn't using, so it was easy to take and install it. Since it fixed the problem, I didn't do anything else.
The thermocouple readings in the next roast were fixed, no bouncing in the next roast. But screen still went blank.
So I made a somewhat kludgy change to recover if the LCD goes blank, see the LCD Blanking Fix section towards the end of this page.
Bluetooth worked at first, but then I had troubles getting it to connect to my windows microsoft surface. Found this, https://github.com/espressif/arduino-esp32/issues/5164
So I rolled back my esp32 library to Ver 1.0.4 instead of 1.0.6. Seems to have worked, now I have a working bluetooth connection. I can't be too far away like the other side of the house, but can have the Surface PC in the garage while the roaster is outside at the side of the house.
Later had more connection problems, so I moved from windows to a very old macbook. Macbook has no bluetooth problems.
Compile with Arduino 2.3.2
Debounce switches
https://www.switchdoc.com/2018/04/esp32-tutorial-debouncing-a-button-press-using-interrupts/
added 2.4k external pullup resistors instead of using internal pullups
added cap from switch gpio to ground if switch was on IO33, Button 1, was getting many false positives
https://www.letscontrolit.com/forum/viewtopic.php?t=9785
Fix PMW for new Library
ledcAttach(HeatPin, freq, resolution);
//intialize pwm to output initial value
PWMDutyCycle = map(dutyCycle, 0, 99, 1, MaxDutyCycle);
//turn heater on at startup
ledcWrite(HeatPin, PWMDutyCycle);
Software is at gitlab
Copied bluetooth info from here https://github.com/hokoon/RoastESP32/blob/master/RoastESP32.ino
I program the software into ESP32 using the Arduino tools.
After its programmed once, you can use AsyncElegantOTA to program after that. Programs over wi-fi.
For this to work, you need to put your wifi SSID and password into the Credentials.h file.
Low Frequency PWM
https://forum.arduino.cc/t/esp32-what-is-the-minimum-pwm-frequency/671077/2
https://www.esp32.com/viewtopic.php?t=32421
// ESP32: Output PWM 0.1Hz (10 second period), 50% duty-cycle on GPIO pin 27
#include "soc/mcpwm_reg.h"
#include "soc/mcpwm_struct.h"
#include "driver/mcpwm.h"
#define GPIO_PWM0A_OUT 27
void setup() {
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT); // Initialise channel MCPWM0A on GPIO pin 27
MCPWM0.clk_cfg.prescale = 199; // Set the 160MHz clock prescaler to 199 (160MHz/(199+1)=800kHz)
MCPWM0.timer[0].period.prescale = 199; // Set timer 0 prescaler to 199 (800kHz/(199+1))=4kHz)
MCPWM0.timer[0].period.period = 39999; // Set the PWM period to 0.1Hz (4kHz/(39999+1)=0.1Hz)
MCPWM0.channel[0].cmpr_value[0].val = 20000; // Set the counter compare for 50% duty-cycle
MCPWM0.channel[0].generator[0].utez = 2; // Set the PWM0A ouput to go high at the start of the timer period
MCPWM0.channel[0].generator[0].utea = 1; // Clear on compare match
MCPWM0.timer[0].mode.mode = 1; // Set timer 0 to increment
MCPWM0.timer[0].mode.start = 2; // Set timer 0 to free-run
}
void loop() {}
Analog Input
0 V corresponds to 0, and 3.3 V corresponds to 4095, but not linear at high end.
From Arduino library manager. Search then install these in Arduino, Tools > Manage Libraries
AsyncElegantOTA
TelnetStream (only if you want to use telenet for debugging help)
Download these zip files:
https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip
https://github.com/marcoschwartz/LiquidCrystal_I2C Only need if using I2C LCD
Select green code button, then download zip. Unzip and copy to arduino libraries
If you get this type of error message at end of compilation
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
.
.
.
exit status 1
Error compiling for board WEMOS D1 MINI ESP32.
Need to do the following steps from Terminal
https://forum.arduino.cc/t/exec-python-executable-file-not-found-in-path/971847/15
sed -i -e 's/=python /=python3 /g' ~/Library/Arduino15/packages/esp32/hardware/esp32/*/platform.txt
https://osxdaily.com/2021/07/19/fix-xcrun-error-invalid-active-developer-path-error-terminal-mac/
xcode-select --install
https://forum.arduino.cc/t/how-to-program-a-d1-mini-esp32/626684
GND to ground TXD NC RST GND
IO27 TC4 IO9 PWM Heat RXD NC SVP NC
IO25 thermoCS IO22 I2C0 SCL LCD IO26 thermoCLK SVN
IO32 IO21 I2C- SDA LCD IO18 But0 grey IO35 Pot input
TDI IO17 IO19 thermo2CS IO33 thermoDO
IO4 IO16 But 2 IO23 But 3 IO34
IO0 GND IO5 thermo2CLK TMS
IO2 VCC 5V Red 3.3V to TC4 5V orange NC
SD1 TDO TCK SD2
CLK SD0 SD3 CMD
(but = button)
ADC1 pins GPIO32, 33,34, 35, 36, 39
only use pins 11,12,13,18,23,24,25,26,29 and 30 as SDA or SCK
12, 18, 23, 25, 26,
SPI Pins (for max6675)
sck gpio5, cs gpio23, so gpio19
old
GND to ground TXD NC RST GND
IO27 TC4 IO9 PWM Heat RXD NC SVP NC
IO25 I2C1 SDA IO22 I2C0 SCL TC4/LCD IO26 I2C1 SCL SVN
IO32 IO21 I2C- SDA TC4/LCD IO18 But0 grey IO35
TDI IO17 IO19 But 4 IO33 But 1 brown
IO4 IO16 But 2 IO23 But 3 IO34
IO0 GND IO5 TMS
IO2 VCC 5V Red 3.3V to TC4 5V orange NC
ESP32 is setup like the picture below. I soldered pins into the ESP32 board, and headers on a breadboard. The ESP32 plugs into the breadboard, and all wires to the LCD, TC4, etc connect to the bottom of the breadboard.
So I can easily swap out the ESP32 if I need to.
I2C SCL ESP32 IO22 to TC4 J2-6 to LCD SCL
I2C SDA ESP32 IO21 to TC4 J2-5 to LCD SDA
+5 to LCD VCC
Gnd to LCD GND
LCD connection below:
MAX6675
https://robojax.com/learn/arduino/?vid=robojax_ESP32_MAX6675_multiple used pinouts from here
https://randomnerdtutorials.com/esp32-k-type-thermocouple-max6675/
Need m6 nut for threaded TC
robojax code for init:
#include "max6675.h"
//for sensor 2
int thermoCLK2 = 26;
int thermoCS2 = 25;
int thermoDO2 = 33;
float tempC2, tempF2, tempK2;
//for sensor 3 do as above,define pins
char *titleTemp="Temperature: ";
int type=2;// 1=C, 2=F, 3=K,
MAX6675 thermocouple1(thermoCLK1, thermoCS1, thermoDO1);
MAX6675 thermocouple2(thermoCLK2, thermoCS2, thermoDO3);
//for 3rd MAX6675 thermocouple3(thermoCLK3, thermoCS3, thermoDO3);
/////////////// end of MAX6675 settings
Standard Connections
GPIO23 CS
GPIO19 SO
GPIO5 SCK
Connect as follows:
POWER
3.3V pin from ESP32 to 5V in (power connector pin 4).
ESP32 ground to TC4 ground
Note: With connections above, TC4 board is powered with 3.3V, so in schematic below all places where it says 5V is actually 3.3V. But all the parts are rated to work down to 3.3V, so this works fine. 5VDC is connected to the Vin pin which is used by the SSR driver outputs circuit in the lower left box.
Connect 5VDC from 7805 to Vin (power connector pin 6)
LOGIC and Thermocouple
I2C: analog input pins A4 (SDA) and A5 (SCL)
For ESP32, I2C pins are GPIO 22 (SCL) and GPIO 21 (SDA)
ESP32 IO22 TC4 J2-6 SCL
ESP32 IO21 TC4 J2-5 SDA
ESP32 IO27 TC4 J3-2 DIO9 PWM Heat
ESP32 IO32 TC4 J3-3 DIO9 PWM Spare (not used)
TC input ch 1 to bean temp TC connector
TC input ch 2 to environmental temp TC connector
OT1+ to Heater Switch to Heater SSR In+
OT1- to Heater SSR In-
TC4 schematic.
I have an older version that does not have the EEPROM circuit.
#define SDA_2 25
#define SCL_2 26
setup(){
Wire.begin(); //uses default SDA and SCL and 100000HZ freq
Wire1.begin(SDA_2, SCL_2, 100000 ); }
TwoWire I2Cone = TwoWire(0);
TwoWire I2Ctwo = TwoWire(1)
void setup() {
I2Cone.begin(SDA_1, SCL_1, freq1);
I2Ctwo.begin(SDA_2, SCL_2, freq2);
}
IO32 CS
IO4 DI
IO0 DO
IO2 CLK
// Use software SPI: CS, DI, DO, CLK
Adafruit_MAX31865 thermo = Adafruit_MAX31865(32, 4, 0, 2);
Vin - this is the power pin. Since the chip uses 3 VDC, we have included a voltage regulator on board that will take 3-5VDC and safely convert it down. To power the board, give it the same power as the logic level of your microcontroller - e.g. for a 5V micro like Arduino, use 5V
3Vo - this is the 3.3V output from the voltage regulator, you can grab up to 100mA from this if you like
GND - common ground for power and logic
RDY (Ready) - is a data-ready indicator pin, you can use this pin to speed up your reads if you are writing your own driver. Our Arduino driver doesn't use it to save a pin
Need to install the Adafruit MAX31865 library.
It also needed me to install this other library
In Arduino, go to Files, Examples, Examples from Custom Libraries, Adafruit MAX31865 library the pick its example to see example code
ESP32 compilation errors
Had to go to Library Manager, find Adafruit BusIO, and change to us version 1.9.6
Then it would compile without errors
PT100 uses a 400 ohm reference resistor, and a PT1000 uses a 4k reference resistor
4kΩ, 10ppm/°C temperature coefficient, ±0.1% tolerance
To fix the problem where my LCD sometimes blanks out and doesn't recover, I had to make a software and hardware change.
Its a band aid because it doesn't fix the root cause of the problem, but it does let you get the LCD back, will see how well this works while roasting.
The hardware changes is I added a momentary switch on the +5VDC VCC to the LCD.
The switch is wired so when its in the normal position, +5V goes to the LCD, and the LCD works normally.
When you press the switch, it will open the +5V line, cutting power to the LCD. Release the switch and +5V is restored, LCD has power again but it has been reset.
At this point, I would only see garbage on the LCD, nothing readable.
So I made a software change to initialize the LCD every 10 loops. See code below
int ResetCnt = 0; //counter to use to reset LCD
//Reset LCD after 10 counts
ResetCnt++;
if (ResetCnt >= 10) {
lcd.init();
lcd.backlight(); // turn on LCD backlight
lcd.setCursor( 0, 0 );
ResetCnt = 0;
}
As far as I can tell, there is no drawback to initializing the LCD this often.
You will see the LCD blink when this init code runs, but blink is short.
When the code runs, the garbage chars will turn back into the normal screen.
const int MAX_DUTY_CYCLE = (int)(pow(2, PWMResolution) - 1);
For resolution = 10, max duty cycle = 1023
map(value, fromLow, fromHigh, toLow, toHigh)
map(DutyCycle, 1, 100, 1, 1023)
PWMDutyCycle = map(dutyCycle, 1, 100, 1, MaxDutyCycle);
I tried this, but it didn't work.
Software is at gitlab
Websockets
https://artisan-scope.org/devices/websockets/
https://github.com/Links2004/arduinoWebSockets/
Artisan sends:
{ 'command': 'getData', 'id': 44683, 'machine': 0 }{ 'command': 'getData', 'id': 44683, 'machine': 0 }
Response
{ "id": 44683, "data": { "BT": 189.2, "ET": 220.5 } }
Software switch debounce notes:
https://lastminuteengineers.com/handling-esp32-gpio-interrupts-tutorial/
struct Button {
const uint8_t PIN;
bool pressed;
};
Button button1 = {18, 0, false};
//variables to keep track of the timing of recent interrupts
unsigned long button_time = 0;
unsigned long last_button_time = 0;
void IRAM_ATTR isr() {
button_time = millis();
if (button_time - last_button_time > 250)
{
button1.numberKeyPresses++;
button1.pressed = true;
last_button_time = button_time;
}
}