digitaltrails / vdu_controls

VDU controls - a control panel for monitor brightness/contrast/...
GNU General Public License v3.0
118 stars 4 forks source link

GY30/BH1750 + Arduino Lux metering potential options #45

Closed digitaltrails closed 1 year ago

digitaltrails commented 1 year ago

A simple light meter can be build using an Arduino and a GY30/BH1750 sensor. [Removed reference to dead link]

This raises some possibilities for vdu_controls to initiate transitions depending on metered light levels.

Today I built a meter using an Arduino Nano - image of wiring: 20230304_171125b

A simple Sketch using Christopher Laws' BH1750 library can be uploaded to the Arduino to retrieve a feed of Lux values:

#include <BH1750.h>
#include <Wire.h>

BH1750 lightMeter;

void setup() {
…  // Serial.println(F("BH1750 Lux values stream..."));
}

void loop() {
  float lux = lightMeter.readLightLevel();
  Serial.println(lux);
  delay(1000);
}

The feed of Lux values can be read from the USB tty on a Linux host. This feed can be used to trigger presets by issuing Linux signals (an existing capability of vdu_controls):

import os
import time

import serial
from serial import SerialException
import psutil

class Level:

    def __init__(self, min_level, max_level, signal) -> None:
        super().__init__()
        self.min = min_level
        self.max = max_level
        self.signal = signal

# (Min light level, max light level, UNIX signal number for Preset)
LEVELS = [Level(100, 200, 40), 
          Level(201, 300, 41),
          Level(300, 900, 42)]

def signal_vdu_controls(signal: int) -> bool:
    for proc in psutil.process_iter():
        if 'vdu_controls' in proc.name():
            pid = proc.pid
            os.kill(pid, signal)
            return True
    return False

try:
    current_level = None
    with serial.Serial('/dev/ttyUSB0') as gy30:
        while True:
            try:
                buffer = gy30.readline()
                value = float(buffer.decode('utf-8').replace("\r\n", ''))
                print(f"lux={value:6.2f}")
                for level in LEVELS:
                    if level != current_level:
                        if level.min <= value <= level.max:
                            print("signal")
                            if signal_vdu_controls(level.signal):
                                current_level = level
                            time.sleep(120)
            except ValueError as ve:
                print(ve, buffer)
except SerialException as se:
    print(se)

The above works and triggers presets according to the specified levels.

The issue is, how best to integrate this:

Parking all of the above, pending time to properly investigate it.

digitaltrails commented 1 year ago

OK, in case anyone is interested in this issue, I've added the following to vdu_controls...

Screenshot_20230319_175353-1a

digitaltrails commented 1 year ago

Integrating Presets to lux metering - one possible approach:

digitaltrails commented 1 year ago

OK, third approach to connecting presets to lux metering:

This seems to work quite well and I will proceed with completing/testing this approach. Working code has been pushed to v1.10 - it appears to be quite stable, but might error on exception cases, such as if a participating preset is altered or deleted:

image

digitaltrails commented 1 year ago

Implemented in version 1.10

major-mayer commented 1 month ago

Shouldn't the sketch code look like this (I took this from the BH1750 lib's documentation and combined it with your existing code)?

#include <BH1750.h>
#include <Wire.h>

BH1750 lightMeter;

void setup() {
  Serial.begin(9600);

  // Initialize the I2C bus (BH1750 library doesn't do this automatically)
  // On esp8266 devices you can select SCL and SDA pins using Wire.begin(D4, D3);
  Wire.begin();

  lightMeter.begin();
  Serial.println(F("BH1750 Lux values stream..."));
}

void loop() {
  float lux = lightMeter.readLightLevel();
  Serial.println(lux);
  delay(1000);
}

In my case, i found it quite confusing that the setup part was not included in the example. Or is this something that differs from device to device?

digitaltrails commented 1 month ago

Shouldn't the sketch code look like this (I took this from the BH1750 lib's documentation and combined it with your existing code)?

...

In my case, i found it quite confusing that the setup part was not included in the example. Or is this something that differs from device to device?

I have no idea why I removed the setup code from the example, perhaps I was worried people might clobber the wrong device or, as you suggest, was worried whether the settings may differ from device to device.

I've added the setup code I'm actually using back into the example.

Thanks for pointing out the issue.

major-mayer commented 1 month ago

Great, glad that I could help 👍