I’m trying to implement some logic in my sketch but can’t get it working. I try to use a CO2 value to calculate a new value and use this. But it won’t work as expected. The value is not making any sense (not does the output).
I tired on_value and on_raw_value, neither work. Looks like the input from the sensor is wrong in the wrong format ? Any and all idea’s are welcome!
Goal is the use the CO level (1193.75ppm for example) to base the led color (amount of RED) on. So 1000 ppm = 0.0 and 1500 ppm is 1.0
[13:49:49][D][scd30:153]: Got CO2=1193.75ppm temperature=21.33°C humidity=45.24%
[13:49:49][D][sensor:092]: 'scd30 CO2': Sending state 1193.75183 ppm with 1 decimals of accuracy
[13:49:49][D][main:504]: Red Number 1 is: -2147483648
[13:49:49][D][main:505]: Input Number is: -536870912
[13:49:49][D][main:506]: Input sensor is: -536870912
[13:49:49][D][main:508]: Red Number 2 is: 536870912
[13:49:49][D][light:265]: 'LED Light' Setting:
[13:49:49][D][light:278]: Brightness: 50%
[13:49:49][D][light:287]: Red=100%, Green=26%, Blue=0%
[13:49:49][D][light:304]: Transition Length: 3.0s
[13:49:49][D][sensor:092]: 'scd30 Temperature': Sending state 21.32587 °C with 1 decimals of accuracy
[13:49:49][D][sensor:092]: 'scd30 Humidity': Sending state 45.24489 % with 1 decimals of accuracy
About the logging.
I may be so that you are trying log the float values but you say they are integer numbers.
My guess there is a printf hiding in the under the ESP_LOGD(…
The “%d” signal that the thing after is an integer. Try to change it to “%f” instead.
Maybe your printout going make more sense.
Note that in the logger component (and i expect in the actual LED logic) the brightness is used to calculate logged %. So 0.5 RED with 0.7 brightness is: (0.5 / 0.7 *1)
I think I made the smarter code you were too lazy to create
The code below will smoothly transition the light from green to yellow and then orange depending on the CO2 value.
- platform: senseair
co2:
name: "CO2 sensor"
id: co2sensor
on_value:
then:
- light.turn_on:
id: rgblicht
state: on
# brightness: 100% need to make this dependent on light sensor, otherwise too bright at night.
# Objective: 400ppm=Green; 900ppm=Yellow; 1200ppm=Red with transitions in between
# -->Between 400ppm and 900ppm Red should gradually increase from 0 to 1: Formula: (X-400)/(900-400) & clamp function will restrict result to be between 0 and 1.
# -->Between 900ppm and 1200ppm Green should gradually decrease from 1 to 0: Formula: 1-(X-900)/(1200-900) & clamp function will restrict result to be between 0 and 1.
red: !lambda |-
static float red_intense = 0.0;
ESP_LOGD("main", "Input Number is: %f", x);
red_intense = ((x-400.0) / 500.0);
ESP_LOGD("main", "Red Number is: %f", red_intense);
red_intense = clamp(red_intense,0.0,1.0);
ESP_LOGD("main", "Red Number clamped is: %f", red_intense);
return red_intense;
green: !lambda |-
static float green_intense = 0.0;
ESP_LOGD("main", "Input Number is: %f", x);
green_intense = (1 - (x-900.0) / 300.0);
ESP_LOGD("main", "Green Number is: %f", green_intense);
green_intense = clamp(green_intense,0.0,1.0);
ESP_LOGD("main", "Green Number clamped is: %f", green_intense);
return green_intense;
blue: 0.0
While I indeed prefer lazy over tired any day, I did modify my code as well after this post. This is to support my CO2 sensor project I build for the school of my kids. You can find all the code et al here on my github: https://github.com/matthijsberg/SCO2/
Glad to hear that.
FYI I see in the code on your github that you still use things like } else if (x > 800 and x < 1500) {
You don’t need this anymore. The clamp functionality will keep de colour values nicely between 0 and 1.
So in the example code I posted above a CO2 PPM of 300 would in principle lead to red being (300-400)/500 which is a negative value, but the clamp function will raise this value to 0.
PS: nice 3d printing skills! That’s an area I haven’t dared to venture into yet
PS2: I was considering to borrow my sensor to my kids school as well because of the COVID-19 pandemic, but my wife thinks they will not want to rely on some DIY thingy :-p
Thanks, I’ll change that in my next iteration (if ever ;-)).
The teachers are really happy with it. I tested 4 of them, with others commercial sensors too, and they where all in the same range. The sensirion sensor is really reliable. Don’t use eCO2 sensors, I found them way off, especially in higher values.
When it’s red they open a door or window, and they see it changing to green really fast again. It’s not too distracting for the kids, yet noticeable enough. I did change the upper limit to 1500 ppm since 1200 is just not doable. Also, 70% red is already really red from a distance.
I plan on building a dashboard for school in HA with all the sensors in it, but I need to add in MQTT since mDNS is disabled at school breaking the websocket integration. (can’t get the IP based fallback to work). When time is on my side again perhaps.
OK, if I see the director of the school I may have a word with him
I chose the senseair S8 over the SCD30 because it’s supposed to have a superior Automatic Background Calibration functionality, also so far people haven’t identified fake versions of the Senseair S8 (supposedly there are a lot of fake SCD30’s).
FYI if you read the values into home assistant (like I do) having a value every 10 seconds is perhaps a bit much to store. My ESP32 reads the value every 4 seconds (because that is the update frequency of the Senseair S8) but I only send the value to Home Assistant if the difference is higher than 4ppm:
filters:
- delta : 4.0 #only send the result if the parts per million difference with the last sent result is higher than this