Too slow ESP32 ouput signal

Hello, I need to power 2 solenoids with the program below, the thing is I need to switch between them fast as sensor is smaller or bigger than the setpoint "regulator_Presiune". I need the pin to send 3.3V output at least 10 to 50 times a second, but it does send only once every 2 seconds, can you give me an advice of how to fix this?

/*
  Sketch generated by the Arduino IoT Cloud Thing "Untitled"
  https://create.arduino.cc/cloud/things/21100e24-8063-4581-843d-1d06721b4799

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  float regulator_Presiune;
  float valoare_reala_presiune;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"
#include <SoftwareSerial.h>

//pinul 32 e conectat la senzorul de presiune
String str;
float pot;
int pinPot = 32;
int ElectromagnetAdmisie = 26;
int ElectromagnetEvacuare = 27;
float pressure; // final pressure in kPa

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is
  pinMode(pinPot, INPUT);
  pinMode(ElectromagnetAdmisie, OUTPUT);
  pinMode(ElectromagnetEvacuare, OUTPUT);
  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
  */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void loop() {
  ArduinoCloud.update();
  
  float  Vout = analogRead(pinPot);
  valoare_reala_presiune = ((Vout/ 4095 )- 0.04) / 0.0018; 
  valoare_reala_presiune = valoare_reala_presiune + 2.5/100 * valoare_reala_presiune;
  valoare_reala_presiune = valoare_reala_presiune * 0.01 + 1.24;// transformam presiunea citita de senzor din kPa in bar
  Serial.print("Presiunea este  ");
  Serial.print(valoare_reala_presiune, 3); // one decimal place
  Serial.println(" bari");

  if (regulator_Presiune>valoare_reala_presiune)
  {
    digitalWrite(ElectromagnetAdmisie, HIGH);
    digitalWrite(ElectromagnetEvacuare, LOW);
  
  }
    else
  {
    digitalWrite(ElectromagnetAdmisie, LOW);
    digitalWrite(ElectromagnetEvacuare, HIGH);
   
  }
}

/*
  Since RegulatorPresiune is READ_WRITE variable, onRegulatorPresiuneChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onRegulatorPresiuneChange()  {
  // Add your code here to act upon RegulatorPresiune change

  str = String(regulator_Presiune);
  Serial2.println(str);
}
/*
  Since ValoareRealaPresiune is READ_WRITE variable, onValoareRealaPresiuneChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onValoareRealaPresiuneChange()  {
  // Add your code here to act upon ValoareRealaPresiune change
}```

What exact type of microcontroller are you using?

You have a single if-else condition that shall switch two valves ON/OFF at 10 to 50 times per second?

The condition to switch ON/OFF is

IoT-variable named "egulator_Presiune" beeing greater or lesser than variable named "valoare_reala_presiune"

the value of these two variables are transferred through IoT-cloud?

The updating of these two variable shall happen 50 times per second?
Which means update once every 20 milliseconds?

Well if you have a internet-ping-time of less than 20 milliseconds guaranteed you are a lucky high-power online-gamer who is willing to pay a lot of money for having such a super-responsive internet-connection.

Let's estimate the communication with IoT takes only 20 bytes per message.
This would mean a daily traffic of 50 times per second * 20 bytes * 3600 secs /hour * 24 h per day = 86.400.000 bytes = 82MB per day.

2,4 GB traffic per month. What do you read in the terms of trade about the monthly traffic for your IoT-connection?

You should describe the whole project in much more details.
Describing your project in much more details enable the other users here to make suggestions how the final purpose of your "thing" can be reached without the need for a high-speed / high-traffic IoT-connection.

Without knowing these details the generalised advice is:
put the microcontroller that measures the variables near to the valves to avoid sending the values over internet.

best regards Stefan

Thank you for the fast response, my project is an IoT pressure regulator, the variable "valoare_reala_presiune" is inputed by an analog pressure sensor and "Regulator_Presiune" is meant to be the setpoint of the desired pressure, that is inputed from my phone using Arduino IoT Cloud dashboard interface. Because the pressure regulator uses normal holding electromagnets, (in industry proportional electromagnets are used, they can hold the moving armature at a certain position controlled via internal feedback) the electromagnets can only be turned on/off, meaning only 2 position for the moving armature, 0 and maximum. Because of that, to obtain similar results as an proportional electromagnet I need to energise the normal electromagnets at least 50 times per second, so because of the moving armature inertia, it will remain at the desired position in between the on/off cycles . The communication with IoT doesn't matter that much, if I change the setpoint its not important that it is instant, from what you told me i should use others variable inside the esp32 to save "Regulator_presiune" and "valoare_reala_presiune" in between the reads?

https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32d_esp32-wroom-32u_datasheet_en.pdf this is the microcontroller that i use

i dont know if its relevant but the electromagnets use 12V to be powered, so i use a B337 transistor to receive command signal from the ESP32 and close the 12V circuit.

Your code is so slow because with each iteration of loop() you update the IoT-variables.

Switching the IO-pins must work independent from your IoT-updating

This can be done in two ways:

using PWM or using a timer-interrupt

With both methods teh switching is done independant from executing

ArduinoCloud.update();

PWM with a mimimum frequency of 100 Hz

EDIT: sorry I took the wrong ESP here are the links for ESP32

Timer-interrupt

best regards Stefan

1 Like

A transistor type BC337 can handle 800 mA.

when switching on/off inductive loads and a coil is an inductive load you need a freewheeling diode. Otherwise the high-voltage-sparks when switching the current off can damage the transistor and maybe even the microcontroller

image

I think PWM should fit my needs, can you give me an idea of how it should look like?
For example in the code I did til now I know that if the pressure is bigger than the setpoint, the ElectromagnetEvacuare (the valve connected to the atmosphere) should open. How should I translate this to PWM? setting the duty cycle of that port to 100% until the condition its no longer true? And if the opposite premise, the pressure lower than setpoint, the duty cycle of ElectromagnetEvacuare port to 0%?

I don't have your hardware. I can't tell exactly.

You will have to make experiments to find how it is working.
100% means 100% current solenoid "opened" completely

0% means 0% current solenoid "closed" completely

The PWM-frequency has an influence on where the solenoid will settle too.

Best thing would be if you post a datasheet and pictures of the solenoids

P30/25 DC12V Electric Sucker Electromagnet 15KG at Rs 420/piece | विद्युत चुम्बक in Mumbai | ID: 24351262273 i looked for a datasheet but i could not find any, this is the electromagnet I'm using

The specs on the website say
|Operating Voltage|12 VDC|
|Max. Operating Current|300 mA|

If your transistor is a BC 337 (not a B 337) a BC337 can handle up to 800 mA.
This means a BC 337 will work
But you need the freewheeling diode like shown here
image

Instead of the relay-coil your electromagnet-coil is connected the same way to the freewheeling diode and the transistor

Do you have freewheeling diodes installed in your setup?
Can you post a picture of the real thing where electromagent and your

If you go on posting only such few information I will wait with the next answer until you have 20 sentences in summary. If it takes takes you a whole month to write 20 sentences it takes a whole month

1 Like

The circuit its almost like the one in the photo ( 1 of those for each electromagnet) ,except that I have 1 more resistance connected between the Rb and transistor in parallel to the ground. I left the whole thing at work and but i can send one to you on Monday if it helps. The transistor is indeed BC337,my bad for misspelling.

image
Also, the power source I use on the 12V circuit offers 2A


This is the whole thing, the electromagnet and the directional valve its encased into on the left its the admission directional valve, on the right its the evacuation directional valve. Only one of those two can be open at once. In the middle the port on up its to the pressure sensor and the bottom its the port for the pressure consumer.
As moving armature I been using an M8 hexagonal Screw.
When the electromagnet its not energized, the helicoidal spring ensure that the directional valve its closed and returns the moving armature to the initial position, 0 mm.
When the electromagnet its energized, the spring its compressed and the directional valve open, displacing the moving armature at final position, d = 0.8mm
So that means when the PWM of the admission directional valve on the left its at max amplitude, the evacuation directional valve PWN should be at 0, by overlaying them it will look like 100% duty cycle

If you write only one of those two (vavles) can be opened at once:

Does this mean even if both electromagnets are powered only one valve will open?
I guess not!
So a more precise description is: only one valve is allowed to be opened.
If the left electromagnet of the left valve is energised the right electromagnet must be without energy to make sure the right valve is closed.

or vice versa

If the right electromagnet of the right valve is energised the left electromagnet must be without energy to make sure the left valve is closed.

Could the valve or anything else be damaged if both valves open at the same time
or is opening both valves at the same time just a not wanted situation but when it should happen there is some noise switch off power and everything is good again wihout any damage?

If there could be damaged something switching on power should be locked against each other in software and in hardware

example code

void AdaptPressure( int Admisie_PWM, int Evacuare_PWM) {

  if (Admisie_PWM > 0 && Evacuare_PWM > 0) { // it is not allowed to open both at the same time
    digitalWrite(ElectromagnetAdmisie,  LOW);// close both
    digitalWrite(ElectromagnetEvacuare, LOW);// valves
      ledcWrite(Admisie_Channel, 0);
      ledcWrite(Evacuare_Channel,0);
    return; // exit function to make really sure trying to open both valves is not possible 
  }

  if (Admisie_PWM > 0) {
      ledcWrite(Admisie_Channel, Admisie_PWM);
      ledcWrite(Evacuare_Channel, 0);
      return;
  }

  if (Evacuare_PWM > 0) {
      ledcWrite(Admisie_Channel, 0);
      ledcWrite(Evacuare_Channel, Evacuare_PWM);
      return;
  }
}
1 Like

Both electromagnets being energised in the same time its just waisting pneumatic and electric energy , the pressure regulator sends all the acumulated pressure back to the atmosphere, so the compressor send flow rate and pressure to the regulator in vain. Both electromagnet being closed may cause hardware damage if kept like that for a long time, the body of the regulator its 3D printed with PETG, so its not 100% safe.

So this part may cause problems but the second and third loop are perfect. From what I see, I will set the duty Cycle to 100% and 100Hz time period,

Change this loop to ledcWrite instead of digitalWrite and then run the AdaptPressure function, and to be sure that Arduino Cloud Update doesn't slow down my process, ill put the code on the other core of ESP32 WROOM (the board processor has 2 cores, one its free)

If you only need 100% dutycycle and never use a dutycycle that is smaller than 100% you can stay with the digitalWrite

But If I understood right you want to switch on off 50 times per second
the function ledcWrite(Evacuare_Channel, Evacuare_PWM); does exactly that only with a frequency of 100 Hz instead of 50 Hz

This switching On/OFF with a frequency of 100 Hz is done in HARDWARE
You don't need to activate a second core or anything else.

There is a PWM-creating hardware inside the chip

You set the dutycycle and then this hardware is creating the PWM
all the time with the set dutycycle until you change the dutycycle or until you disable the PWM.

set and forget

1 Like

as an additional remark:
If your valve is 3D-printed and can't stand the maximum pressure this is planned error-proning
sooner or later it will happen.

It seems that you believe me only after having exploded five 3D-printed valves

1 Like

Im not really sure of what dutycycle i need, for the duty cycle control i should use a PID regulator that gets feedback from the pressure sensor, but i have to do this until monday at noon and i can't afford to complicate myself too much and have nothing to show because of a bug. From what you said above, I should not get rid of digitalWrite? If I do so,I will still get the 2 seconds delay between electromagnet energizing

I cracked it in a few spots, but used resin to fill those up. Thanks God i used transparent PETG on my FDM 3d printer and i can cure resin in between the layers

for setting up the ledcWrite you need

  ledcSetup(ledChannel, freq, resolution);
  ledcAttachPin(IO_Pin, ledChannel);

ledcSetup(ledChannel, freq, resolution);
ledcAttachPin(IO_Pin, ledChannel);
ledcWrite

sets up an INDEPENDENT hardware that creates PWM CONTINIOUSLY
completely independent of what the rest of the code is doing at the moment.
PWM: DOES ALREADY the switching ON/OFF

If you need something different than

check if regulator_Presiune bigger or smaller than valoare_reala_presiune

from time to time = check only once every minute

you have to describe it in much more detail
WHAT this different thing is.

1 Like