]> www.fi.muni.cz Git - bike-lights.git/commitdiff
ambient.c: "entering shadow" detection
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Fri, 19 Jul 2013 19:45:27 +0000 (21:45 +0200)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Fri, 19 Jul 2013 19:45:27 +0000 (21:45 +0200)
We try to detect the rapid decrease in the ambient light level,
such as when entering the dark area (tunnel, deep shadow, etc.).
When this happens, we keep the previous (high) ambient zone,
and use the night pattern (front light continuously on) for at least
3 seconds, to give the rider's eyes the opportunity to adapt.

firmware/ambient.c
firmware/control.c
firmware/lights.h

index 7a5b8e2c3c621f43a3c6aad52a6d5087ab304c1a..7352f6d5779359c2b1b2471091618e0a07641c78 100644 (file)
@@ -7,7 +7,7 @@
 #define AMBIENT_SLOW_SHIFT 6   // 1 << AMBIENT_SLOW_SHIFT times slower
 
 static uint16_t ambient_fast, ambient_slow;
-volatile unsigned char ambient_zone;
+volatile unsigned char ambient_zone, ambient_shadow;
 static unsigned char ambient_min, ambient_max, ambient_drop;
 
 /* logging */
@@ -32,6 +32,8 @@ static ambient_zone_t ambient_zones[N_AMBIENT_ZONES] = {
        { 0x02f8, 0xffff }, // day
 };
 
+#define SHADOW_DROP_LIMIT      0x20 // in ADC units (0..0x3ff)
+
 void init_ambient()
 {
        ambient_slow = 0;
@@ -40,6 +42,7 @@ void init_ambient()
        ambient_min = 0xFF;
        ambient_zone = 1;
        ambient_drop = 0;
+       ambient_shadow = 0;
 
        ambient_log_offset = eeprom_read_byte(&ambient_log_offset_stored);
 
@@ -103,34 +106,60 @@ static unsigned char val_to_zone(uint16_t ambient_val)
 
 void ambient_adc(uint16_t adcval)
 {
-       unsigned char new_zone, user_zone;
+       unsigned char new_zone, user_zone, new_shadow = 0;
        unsigned char byte_fast, byte_slow, drop;
-       uint16_t a_10bit;
+       uint16_t fast_10bit, slow_10bit;
 
        // running avg - shorter timespan
        ambient_fast += adcval - (ambient_fast >> AMBIENT_FAST_SHIFT);
 
        // running avg - longer timespan
-       a_10bit = ambient_fast >> (AMBIENT_FAST_SHIFT + AMBIENT_ADC_SHIFT);
-       ambient_slow += a_10bit - (ambient_slow >> AMBIENT_SLOW_SHIFT);
+       fast_10bit = ambient_fast >> (AMBIENT_FAST_SHIFT + AMBIENT_ADC_SHIFT);
+       ambient_slow += fast_10bit - (ambient_slow >> AMBIENT_SLOW_SHIFT);
 
        // ambient zones are governed by shorter timespan by default
-       new_zone = val_to_zone(a_10bit);
+       new_zone = val_to_zone(fast_10bit);
+
+       slow_10bit = ambient_slow >> AMBIENT_SLOW_SHIFT;
 
        if (new_zone > 1 && (
                new_zone == ambient_zone-1 || new_zone == ambient_zone+1)) {
                // but change to the neighbouring zone is governed by _slow,
                // except to the darkest zone, where we want fast reaction.
-               new_zone = val_to_zone(ambient_slow >> AMBIENT_SLOW_SHIFT);
+               new_zone = val_to_zone(slow_10bit);
        }
 
        // user_param ambient zone override
        if ((user_zone = get_user_param(0)) > 0)
                new_zone = user_zone - 1;
 
+       // are we entering the shadow?
+       if (!user_zone && new_zone < ambient_zone
+               && ambient_zone >= 2 && slow_10bit > fast_10bit
+               && slow_10bit - fast_10bit >= SHADOW_DROP_LIMIT) {
+               // we are entering the shadow
+               new_shadow = 0x30;
+       }
+
+       if (ambient_shadow) {
+               if (new_shadow) {
+                       new_zone = ambient_zone; // don't change while entering shadow
+                       ambient_shadow = new_shadow; // update the timeout
+               } else {
+                       ambient_shadow--;
+                       if (!ambient_shadow) { // leaving the shadow
+                               ambient_zone_changed();
+                       }
+               }
+       } else if (new_shadow) {
+               ambient_shadow = new_shadow; // set up the timeout
+               new_zone = ambient_zone; // don't change while entering shadow
+               ambient_zone_changed();  // notify others the first time
+       }
+
        // TODO: maybe use these values instead of 10-bit?
-       byte_fast = a_10bit >> 2;
-       byte_slow = ambient_slow >> (AMBIENT_SLOW_SHIFT + 2);
+       byte_fast = fast_10bit >> 2;
+       byte_slow = slow_10bit >> 2;
 
        if (byte_slow > byte_fast) {
                drop = byte_slow - byte_fast;
index a0d2451a5df08cd0b095c7438b05bc714bd613c3..2b1a7369f39f24e8b949e0d8e60aa73eb91d18fc 100644 (file)
@@ -140,6 +140,9 @@ pattern_t *pwmled_pattern_select()
        if (err_flags.err_battery)
                return slow_pattern;
 
+       if (ambient_shadow)
+               return night_pattern;
+
        switch (ambient_zone) {
        case 0: return night_pattern;
        case 1:
@@ -185,6 +188,9 @@ pattern_t *illumination_led_pattern_select()
        if (err_flags.err_battery)
                return NULL;
 
+       if (ambient_shadow)
+               return on_pattern;
+
        switch (ambient_zone) {
        case 0: return dim_mode
                ? number_pattern(1, 1)
index 3af09cd9c2555dd93a72670f852e413981b778dd..72d7d33e2ea52d705e520037116ceedb51b2beab 100644 (file)
@@ -81,7 +81,7 @@ void gpio_set(unsigned char n, unsigned char on);
 void init_ambient();
 void susp_ambient();
 void ambient_log_min_max();
-extern volatile unsigned char ambient_zone;
+extern volatile unsigned char ambient_zone, ambient_shadow;
 void ambient_adc(uint16_t adc_val);
 
 /* pattern.c */