vitotai / BrewManiacEsp8266

BrewManiac on ESP8266. Only ESP8266 needed.
155 stars 71 forks source link

How to configure PWM-output for heating ? #75

Open KLelong opened 3 years ago

KLelong commented 3 years ago

Hi, I would like to have a PWM-output for the heating. I looked in the sources and I found that SupportDistilling activates PWM-output. Is there another way ? I don't need distilling, only the PWM-output. Actually, What does SupportDistilling actually do ?

TIA

vitotai commented 3 years ago

During distilling, the controller controls doesn't regulate temperature but just control output in PWM mode.

DartaMan commented 3 years ago

Hi, I'd like to have PWM too, especially after malt is added in the mash stage. Because I’m using a 5kw heater that burns the mash if using 100% power. In my first attempt the beer smells smoke, only found later the PWM variable for boiling. But now I’m afraid to use temperature ramps on mash stage, mash will burn in these temperature changes with 100% power. I’m trying to find were in the code I could change to apply the same boiling PWM factor? Inside PID routine this variable maybe could be used to limit the maximum power too.

vitotai commented 3 years ago

You are using over powerful heating element.

It shouldn't be too difficult to modify the code for you need. You just need to adjust pidOutput before applying it. like

if(pidOutput > maxHeating) pidOutput = maxHeating;
if ((pidOutput / 255) * ((unsigned long)_heatWindowSize * 250) > now - _windowStartTime)
    {
//... 

If you different values for different stages. you will have to modify setting related code and stage related code.

KLelong commented 3 years ago

Hi, To me it sounds as if you don't stir enough. When heating, your liquid has to move ! But if you heat e.g. 10 liters with 5kW, I don't know if you can move your liquid fast enough to avoid burning. Let alone heating without massively overshooting your set temperature. (BTDT, overshoot I mean).

I don't know the volume of your brew, but when I heat 9 liters of water with 1kW I get a delta T of 1°C per minute. I was thought that 1°C per minute is the preferred rate of heating. That is with my test-setup : a cooking-pot with an electrical heating-plate.

For my brewing-installation I need PWM because it has a gas-controller that needs PWM. With it I can control the gas-flame proportionally, not only on/off.

Regards, Koenraad.

vitotai commented 3 years ago

Hi, To me it sounds as if you don't stir enough. When heating, your liquid has to move ! But if you heat e.g. 10 liters with 5kW, I don't know if you can move your liquid fast enough to avoid burning. Let alone heating without massively overshooting your set temperature. (BTDT, overshoot I mean). I don't know the volume of your brew, but when I heat 9 liters of water with 1kW I get a delta T of 1°C per minute. I was thought that 1°C per minute is the preferred rate of heating. That is with my test-setup : a cooking-pot with an electrical heating-plate. For my brewing-installation I need PWM because it has a gas-controller that needs PWM. With it I can control the gas-flame proportionally, not only on/off. Regards, Koenraad.

You can find some information about gas heating on HBT thread. https://www.homebrewtalk.com/threads/yabc-yet-a-brew-controller-brewmaniacex.596907/page-4

I've tried implementing real PWM output, but it didn't seem to work. I blame ESP8266 for not real hardware PWM. ESP32 has hardware PWM output and might work.

P11x3l commented 3 years ago

@vitotai Bumping an old one. What was the problem with PWM output on the 8266?

Just ordered parts to build a controller and manual boil control with a large element is something i'll need to tackle.

KLelong commented 3 years ago

I cut the pwm-code out of BrewManiac and tried that, but for my setup (pwm-control of a gas-burner) ESP8266 is not suited. The PWM controls a coil, at the frequency it uses (don't know exactly but I think about 1kHz), the coils "sings", i.e. it makes a noise. And I don't know if the mechanics of the system will withstand this in the long run. I switched to ESP32, with my own crude software, for the moment, still experimental. There the PWM-frequency is higher : I can set it to 20kHz. Actually I don't see how you can use PWM in an other way than the original BrewmaniacEx to control an electrical system. I think you can use PWM to generate a reference-voltage that controls the firing angle of a triac, but that means more complex hardware than a simple relay. Or are you using DC ?

P11x3l commented 3 years ago

That makes sense I've had similar issues controlling coils in old HDD's, it sounds horrible!

I want to control a 3600w AC element via SSR so I can turn down the boil, at full power it's too strong and over boils. When I saw 'PWM disabled' issues I thought this feature doesn't work, but after reading the manual just now it seems like that when the boil temperature is reached the controller changes over to manual PWM mode to achieve this. Should've RTFM 😅

vitotai commented 3 years ago

The "PWM" in current BrewmaniacEx is derived from Open Ardbir. It's like turning on heating for % of time during 4 to 5 seconds. It's proven and should work with most SSRs. I doubt higher frequency or shorter window time would do better, which might reduce the life-span of SSR, IMO.

The "real" PWM in general sense, is usually in higher frequency, like a few K(s). The most common-seen usage is dimming LEDs. I don't it would work with heating control by SSR, while most SSRs are zero-crossing, and most of us have 50 or 60Hz cycles around the world, in this planet.

There is one situation that "real" PWM is needed, and I've tried. That is PWM-controlled valve for gas heating. The valve will open 50% like when PWM duty is 50%, at 2kHz. Something like that. Unfortunately, ESP8266 doesn't have real hardware PWM, and the waveform seems to be not recognized by the valve. The trial was failed, and the code is not merged, and lost.

acremonezi commented 3 years ago

Could you please someone tell me if is it possible to install it on a ESP32? Best regards

vitotai commented 3 years ago

yes. in 0.5 beta. https://github.com/vitotai/BrewManiacEsp8266/tree/050beta

I haven't built an ESP32 controller, though.

acremonezi commented 3 years ago

@vitotai Very cool! I will build it now! Thanks a lot and best regards!

KLelong commented 3 years ago

Hi, If you succeed to compile it, can you report how you did it ? A few days ago, I tried, but it failed, complaining about the AsyncTCP library not being found. I just downloaded the files, unpacked them and compiled with platformIO.

acremonezi commented 3 years ago

@vitotai @KLelong

Unfortunately I was not able to Build nor Upload 0.5 beta into the ESP32 nor ESP12E using PlatformIO.

I Tried to debug but, unfortunately, with no success... If is there anything I can do to help, just please let me know.

Best regards,

KLelong commented 3 years ago

Just tried again for esp32. I used the github cli to download the code, modified platformio.ini to

[platformio]
env_default =esp32

And then compiled with Visual Studio/platformIO on Kubuntu 20.04 :

> Executing task: pio run <

Warning! `env_default` configuration option in section [platformio] is deprecated and will be removed in the next release! Please use `default_envs` instead
Processing esp32 (platform: espressif32@~2.0.0; board: esp32dev; framework: arduino)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32dev.html
PLATFORM: Espressif 32 (2.0.0) > Espressif ESP32 Dev Module
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (esp-prog) External (esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES: 
 - framework-arduinoespressif32 3.10004.201016 (1.0.4) 
 - tool-esptoolpy 1.20600.0 (2.6.0) 
 - toolchain-xtensa32 2.50200.80 (5.2.0)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 34 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <ArduinoJson> 6.10.0
|-- <FS> 1.0
|-- <EEPROM> 1.0.3
|-- <OneWire>
|-- <PID_AutoTune_v0>
|-- <PID_v1>
|-- <ArduinoOTA> 1.0
|   |-- <Update> 1.0
|   |-- <WiFi> 1.0
|   |-- <ESPmDNS> 1.0
|   |   |-- <WiFi> 1.0
|-- <AsyncTCP> 1.1.0
|-- <ESP Async WebServer> 1.2.2
|   |-- <AsyncTCP> 1.1.0
|   |-- <FS> 1.0
|   |-- <WiFi> 1.0
|   |-- <ArduinoJson> 6.10.0
|-- <ESPmDNS> 1.0
|   |-- <WiFi> 1.0
|-- <SPIFFS> 1.0
|   |-- <FS> 1.0
|-- <WiFi> 1.0
|-- <Wire> 1.0.1
|-- <Update> 1.0
|-- <WebServer> 1.0
|   |-- <WiFi> 1.0
|   |-- <FS> 1.0
|-- <HTTPClient> 1.2
|   |-- <WiFi> 1.0
|   |-- <WiFiClientSecure> 1.0
|   |   |-- <WiFi> 1.0
|-- <DNSServer> 1.1.0
|   |-- <WiFi> 1.0
|-- <ESP8266_SSD1306> 4.0.0
|   |-- <Wire> 1.0.1
|-- <LiquidCrystal_I2C_V3-master>
|   |-- <Wire> 1.0.1
Building in release mode
Compiling .pio/build/esp32/src/BackupService.cpp.o
Compiling .pio/build/esp32/src/BrewManiac.cpp.o
In file included from src/BrewManiac.cpp:14:0:
lib/OneWire/src/OneWire.h:245:2: warning: #warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture." [-Wcpp]
 #warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture."
  ^
Compiling .pio/build/esp32/src/BrewManiacEx.cpp.o
src/BrewManiacEx.cpp: In member function 'void NetworkConfig::loadSetting()':
src/BrewManiacEx.cpp:46:53: warning: format '%d' expects argument of type 'int', but argument 3 has type 'ArduinoJson6100_000::DeserializationError' [-Wformat=]
 #define DBG_PRINTF(...) DebugPort.printf(__VA_ARGS__)
                                                     ^
src/BrewManiacEx.cpp:605:3: note: in expansion of macro 'DBG_PRINTF'
   DBG_PRINTF("deserialzeJson:%d\n",error);
   ^
Compiling .pio/build/esp32/src/BrewManiacWeb.cpp.o
Compiling .pio/build/esp32/src/ESP32HTTPUpdateServer.cpp.o
Compiling .pio/build/esp32/src/ESPUpdateServer.cpp.o
Compiling .pio/build/esp32/src/EmbeddedFiles.cpp.o
Compiling .pio/build/esp32/src/FsEeprom.cpp.o
Compiling .pio/build/esp32/src/HttpUpdateHandler.cpp.o
src/HttpUpdateHandler.cpp:5:22: fatal error: AsyncTcp.h: No such file or directory

******************************************************************
* Looking for AsyncTcp.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:AsyncTcp.h"
* Web  > https://platformio.org/lib/search?query=header:AsyncTcp.h
*
******************************************************************

compilation terminated.
*** [.pio/build/esp32/src/HttpUpdateHandler.cpp.o] Error 1
Compiling .pio/build/esp32/src/WiFiSetup.cpp.o
==================================================================================== [FAILED] Took 8.00 seconds ====================================================================================

Environment    Status    Duration
-------------  --------  ------------
esp32          FAILED    00:00:07.997
=============================================================================== 1 failed, 0 succeeded in 00:00:07.997 ===============================================================================

AFAIKT AsyncTCP is there in lib-esp32, because I removed the directory and then the "dependency finder" does not show the library.

KLelong commented 3 years ago

Sorry about the noise, I just realised it could be a "case-case" ;-) Just checked if the case of the file was OK and it was not. I changed it in the source and now it compiles. It's in HttpUpdateHandler.cpp, line 5 in my version.

KLelong commented 3 years ago

I got it running, but my temp-sensor is not detected. It's an older sensor, ID : 10 CA 67 AC 0 8 0 26 I made an Arduino sketch using the same pin (23), there it's detected OK. I tried some things to write the ID, but it seems not detected at all. I get the same values without the sensor. In platformio.ini I set FakeHeating to false. My modded code (BrewManiac.cpp, starting at line 813) :

#if SerialDebug == true
        char pbuf[20];
        printSensorAddress(pbuf,gSensorAddresses[i]);
        Serial.printf("Sensor: addr:%d, 0x%s\n",base,pbuf);
#endif

        if (((gSensorAddresses[i][0] != 0x28) && (gSensorAddresses[i][0] != 0x10 ))
                || OneWire::crc8( gSensorAddresses[i], 7) != gSensorAddresses[i][7]) {
            DBG_PRINTF("invalid sensor address byte1 ! %x\n",gSensorAddresses[i][0]);
            DBG_PRINTF("invalid sensor address! %x\n",gSensorAddresses[i]);
            DBG_PRINTF("invalid sensor address crc! %x\n",OneWire::crc8( gSensorAddresses[i], 7));
            break;
        }

Resulting values :

Sensor: addr:112, 0x000000006F726B2E
invalid sensor address byte1 ! 0
invalid sensor address! 3ffc179b
invalid sensor address crc! 98

Any thoughts ? TIA

acremonezi commented 3 years ago

@KLelong

You got it! Congratulations!

I have just replaced #include <AsyncTcp.h> to #include <AsyncTCP.h>

And I was able to Build and Upload the code to ESP32.

The result: image

Now I will test it out!

Thanks and Best regards,

acremonezi commented 3 years ago

I got it running, but my temp-sensor is not detected. It's an older sensor, ID : 10 CA 67 AC 0 8 0 26 I made an Arduino sketch using the same pin (23), there it's detected OK. I tried some things to write the ID, but it seems not detected at all. I get the same values without the sensor. In platformio.ini I set FakeHeating to false. My modded code (BrewManiac.cpp, starting at line 813) :

#if SerialDebug == true
      char pbuf[20];
      printSensorAddress(pbuf,gSensorAddresses[i]);
      Serial.printf("Sensor: addr:%d, 0x%s\n",base,pbuf);
#endif

      if (((gSensorAddresses[i][0] != 0x28) && (gSensorAddresses[i][0] != 0x10 ))
              || OneWire::crc8( gSensorAddresses[i], 7) != gSensorAddresses[i][7]) {
          DBG_PRINTF("invalid sensor address byte1 ! %x\n",gSensorAddresses[i][0]);
          DBG_PRINTF("invalid sensor address! %x\n",gSensorAddresses[i]);
          DBG_PRINTF("invalid sensor address crc! %x\n",OneWire::crc8( gSensorAddresses[i], 7));
          break;
      }

Resulting values :

Sensor: addr:112, 0x000000006F726B2E
invalid sensor address byte1 ! 0
invalid sensor address! 3ffc179b
invalid sensor address crc! 98

Any thoughts ? TIA

@KLelong

I already have the same issue. No sensor is detected.

I enabled multisensor and nothing was find as well.

build_flags =
    -DOLED_LCD=true
    -DSerialDebug=true
    -DMultipleSensorEnabled=true

I believe we need superior help.

Best regards,

vitotai commented 3 years ago

When I ported BME to ESP32, I had similar problem. I had no idea and changed to other PIN. It worked, and then I found some of the PINs just had issues. I am not sure if my breadboard or ESP32 board has something to do with it. There is much to do for software in this case. The only one I can think of is timing, but it's hard for me to verify without some equipment, like logic analyzers. Maybe you can change the resistor to 10K, or supplying 5V to DS18B20. I don't know. Update: Updated OneWire library. Please try with your luck.

KLelong commented 3 years ago

Hi, Progress ! I discovered that the sensor(s) need to be detected by the web-gui : Settings/Edit/Scan Sensor. Then my sensor is detected and when saved I see the sensor is active at boot. I had to tweak the source for my sensor (0x10 type). I'm going to try and make a version for all DS1820 types, like in the library-example I used for my own tests. I don't know if I have other sensors to try, though.

vitotai commented 3 years ago

Addresses starting with 0x10 is ds18S20, not ds18B20. You can do whatever you want, but I don't see the point to support other sensors.

KLelong commented 3 years ago

Hi, I don't understand your point, but this is the diff :

772c772
<       if ((addresses[m][0] != 0x28) && (addresses[m][0] != 0x10))
---
>       if (addresses[m][0] != 0x28)
819c819
<       if (((gSensorAddresses[i][0] != 0x28) && (gSensorAddresses[i][0] != 0x10 ))
---
>       if (gSensorAddresses[i][0] != 0x28
955,961d954
<       if (addr[0]==0x10){
<       raw = raw << 3;
<               if (sensorData[7]==0x10) {
<                       raw = (raw & 0xFFF0) + 12 - sensorData[6];
<                       }
<       }
<       else {
963c956
<               gSensorResolution=sensorData[4] & 0x60;
---
>       gSensorResolution=sensorData[4] & 0x60;
966,970c959,963
<       if (gSensorResolution == 0x00) raw = raw & ~7;  // 0.5C 9 bit resolution, 93.75 ms
<       else if (gSensorResolution == 0x20) raw = raw & ~3; // 0.25C 10 bit res, 187.5 ms
<       else if (gSensorResolution == 0x40) raw = raw & ~1; // 0.125C 11 bit res, 375 ms
<               // 0x60  0.0625C 12bits, 750ms
<       }
---
>     if (gSensorResolution == 0x00) raw = raw & ~7;  // 0.5C 9 bit resolution, 93.75 ms
>     else if (gSensorResolution == 0x20) raw = raw & ~3; // 0.25C 10 bit res, 187.5 ms
>     else if (gSensorResolution == 0x40) raw = raw & ~1; // 0.125C 11 bit res, 375 ms
>       // 0x60  0.0625C 12bits, 750ms
> 

In short : two lines modified, 7 lines added. Tested with my sensors, and a DS18B20 I found in my component-stash. That's an SMD-component, not suited for my sensors, mounted in a stainless steel tube.

KLelong commented 3 years ago

I forgot to tell I also tested on pin 19. I have a PCB with my controller hardware on it. There I use pin 19 to connect the sensors.