From 6f3f8fa6f569ede97046be5365953c0e1ef167bf Mon Sep 17 00:00:00 2001 From: Vitalii Popov Date: Sat, 17 May 2025 21:34:41 +0300 Subject: [PATCH] updating "turning off" & test added adc (light) --- _common/stm8s103f3.h | 12 ++- src/main.c | 177 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 155 insertions(+), 34 deletions(-) diff --git a/_common/stm8s103f3.h b/_common/stm8s103f3.h index 9117573..768f862 100644 --- a/_common/stm8s103f3.h +++ b/_common/stm8s103f3.h @@ -61,6 +61,16 @@ #define I2C1 (*(volatile I2C*) 0x5210) #define CLK (*(Clock*) 0x50C0) #define WWDG (*(Watchdog*) 0x50D1) +#define ADC1_BUFFER0 (*(ADCBuffer*) 0x53E0) +#define ADC1_BUFFER1 (*(ADCBuffer*) 0x53E2) +#define ADC1_BUFFER2 (*(ADCBuffer*) 0x53E4) +#define ADC1_BUFFER3 (*(ADCBuffer*) 0x53E6) +#define ADC1_BUFFER4 (*(ADCBuffer*) 0x53E8) +#define ADC1_BUFFER5 (*(ADCBuffer*) 0x53EA) +#define ADC1_BUFFER6 (*(ADCBuffer*) 0x53EC) +#define ADC1_BUFFER7 (*(ADCBuffer*) 0x53EE) +#define ADC1_BUFFER8 (*(ADCBuffer*) 0x53F0) +#define ADC1_BUFFER9 (*(ADCBuffer*) 0x53F2) #define ADC1 (*(ADC*) 0x5400) #define TIM2 (*(GeneralTimer*) 0x5300) @@ -71,4 +81,4 @@ #define CFG_GCR (*(u08*) 0x7F60) #define IWATCHDOG (*(IndependWatchdog*) 0x50E0) -#endif//STM8S103F3_DEF \ No newline at end of file +#endif//STM8S103F3_DEF diff --git a/src/main.c b/src/main.c index 8b8ca26..147ba82 100644 --- a/src/main.c +++ b/src/main.c @@ -12,6 +12,7 @@ #define AMOUNT_DISTANCE_MEASURE 8 #define ACTIVATION_DISTANCE 40 +#define MIN_LIGHT 512 // LED pin info #define LED_PIN_DIR PORT_C.DDR.Pin3 @@ -31,6 +32,12 @@ #define TX_PIN_CR2 PORT_D.CR2.Pin5 #define TX_PIN_OUT PORT_D.ODR.Pin5 +#define LIGHT_PIN_DIR PORT_D.DDR.Pin3 +#define LIGHT_PIN_CR1 PORT_D.CR1.Pin3 +#define LIGHT_PIN_CR2 PORT_D.CR2.Pin3 +#define LIGHT_PIN_OUT PORT_D.ODR.Pin3 + +#define LIGHT_CHANNEL 4 #define PRESS_ACTIVATION_TIME 30 * 4 #define SENSE_ACTIVATION_TIME PRESS_ACTIVATION_TIME @@ -61,6 +68,8 @@ u08 state = 0; u08 led_state = 0; u16 last_distance[AMOUNT_DISTANCE_MEASURE] = {0}; u08 distance_count = 0; +u16 light_level = 1024; +u08 disable_until_lost = 0; /** * Hang processor with big delay and hope for watchdog to kick-in or directly @@ -126,12 +135,97 @@ i16 elapsed(void) { return next / 10 + full_tick * 250; } +/** + * Calculate average distance from last N measurements + * Note: returns 0 if no measurements done + */ +u16 avg_distance(void) { + u16 sum = 0; + u08 cnt = 0; + for (u08 i = 0; i < AMOUNT_DISTANCE_MEASURE; i++) { + sum += last_distance[i]; + if (last_distance[i] > 0) { + cnt++; + } + } + if (cnt > 0) { + return sum / cnt; + } + return 0; +} + +void hex_byte(u08 b, u08 p) { + tx_buffer[p] = (((b & 0xF0) >> 4) + '0'); + if (tx_buffer[p] > 57) { + tx_buffer[p] += 7; + } + tx_buffer[p + 1] = ((b & 0x0F) + '0'); + if (tx_buffer[p + 1] > 57) { + tx_buffer[p + 1] += 7; + } +} + void send_some_command(void) { - tx_buffer[0] = 'C'; - tx_buffer[1] = 'M'; - tx_buffer[2] = 'D'; - tx_buffer[3] = '\n'; - start_cmd(4); +/* + u08 t = (light_level & 0xF000 >> 12) + '0'; + if (t > 57) { + t += 7; + } + tx_buffer[0] = t; + t = (light_level & 0x0F00 >> 8) + '0'; + if (t > 57) { + t += 7; + } + tx_buffer[1] = t; + t = (light_level & 0x00F0 >> 4) + '0'; + if (t > 57) { + t += 7; + } + tx_buffer[2] = t; + t = (light_level & 0x000F >> 0) + '0'; + if (t > 57) { + t += 7; + } + tx_buffer[3] = t; + tx_buffer[4] = '\r'; + tx_buffer[5] = '\n'; + start_cmd(6); +*/ + u08 p = 0; + tx_buffer[p++] = 'S'; + tx_buffer[p++] = led_state ? '1' : '0'; + tx_buffer[p++] = ' '; + tx_buffer[p++] = 'T'; + hex_byte(full_tick, p); + p += 2; + tx_buffer[p++] = ' '; + tx_buffer[p++] = 'X'; + tx_buffer[p++] = is_countdown_active() ? '1' : '0'; + tx_buffer[p++] = ' '; + tx_buffer[p++] = 'J'; + tx_buffer[p++] = disable_until_lost + '0'; + tx_buffer[p++] = ' '; + tx_buffer[p++] = 'L'; + hex_byte(light_level >> 8, p); + p += 2; + hex_byte(light_level & 0xff, p); + p += 2; + tx_buffer[p++] = ' '; + tx_buffer[p++] = 'D'; + i16 d = avg_distance(); + hex_byte(d >> 8, p); + p += 2; + hex_byte(d & 0xff, p); + p += 2; + tx_buffer[p++] = ' '; + tx_buffer[p++] = 'U'; + hex_byte(timer >> 8, p); + p += 2; + hex_byte(timer & 0xff, p); + p += 2; + tx_buffer[p++] = '\r'; + tx_buffer[p++] = '\n'; + start_cmd(p); } /** @@ -161,6 +255,7 @@ void turn_on(void) { } led_state = 1; u16 delay = LED_FADE_TIME; +// send_some_command(); while (delay > 1) { LED_PIN_OUT ^= 1; delay_tick(delay); @@ -179,6 +274,7 @@ void turn_off(void) { } led_state = 0; u16 delay = 1; +// send_some_command(); while (delay < LED_FADE_TIME) { LED_PIN_OUT ^= 1; delay_tick(delay); @@ -187,25 +283,6 @@ void turn_off(void) { LED_PIN_OUT = 0; } -/** - * Calculate average distance from last N measurements - * Note: returns 0 if no measurements done - */ -u16 avg_distance(void) { - u16 sum = 0; - u08 cnt = 0; - for (u08 i = 0; i < AMOUNT_DISTANCE_MEASURE; i++) { - sum += last_distance[i]; - if (last_distance[i] > 0) { - cnt++; - } - } - if (cnt > 0) { - return sum / cnt; - } - return 0; -} - /** * Tick event handler */ @@ -216,6 +293,9 @@ void tick_250ms(void) { // and skip other tasks if not finished return; } + CLK.Peripheral2.AnalogDigitalConvertor = 1; + delay_tick(0x20); + ADC1.Configuration1.ConverterOn = 1; if (is_countdown_active() && full_tick < 255) { full_tick++; } @@ -225,13 +305,17 @@ void tick_250ms(void) { } if (timer == 0) { u16 distance = avg_distance(); - if (distance != 0 && distance < ACTIVATION_DISTANCE) { - timer = SENSE_ACTIVATION_TIME; + if (distance != 0) { + if (disable_until_lost == 0 && light_level <= MIN_LIGHT && distance < ACTIVATION_DISTANCE) { + timer = SENSE_ACTIVATION_TIME; + } else if (distance >= ACTIVATION_DISTANCE) { + disable_until_lost = 0; + } + } + if (elapsed() > LONG_PRESS_MS) { + timer = -1; + stop_countdown(); } - } - if (elapsed() > LONG_PRESS_MS) { - timer = -1; - stop_countdown(); } // If we still have time // note: timer can be below zero to work without timer @@ -254,7 +338,7 @@ int is_rx_finished(void) { } // Check head, tail and just in case - length return - (rx_buffer[0] == RANGE[0] && + (rx_buffer[0] == RANGE[0] && rx_buffer[1] == RANGE[1] && rx_buffer[2] == RANGE[2] && rx_buffer[3] == RANGE[3] && @@ -280,7 +364,7 @@ void add_distance(u16 distance) { */ void process_rx(void) { if (rx_buffer[0] == RANGE[0]) { - u16 distance = 0; + u16 distance = 0; for (u08 i = 6; i <= rx_pos; i++) { if (rx_buffer[i] >= '0' && rx_buffer[i] <= '9') { distance = distance * 10 + (rx_buffer[i] - '0'); @@ -355,6 +439,7 @@ interrupt(IRQ_EXTI_C, touch) { timer = PRESS_ACTIVATION_TIME; // 30 seconds * 4 (250ms tick) } else { // Or turn it off + disable_until_lost = 1; timer = 0; } } @@ -369,6 +454,16 @@ interrupt(IRQ_TIM1_OVERFLOW, timer1_tick) { tick_250ms(); } +interrupt(IRQ_ADC_END, adc_done) { + u08 low = ADC.Data.Low; + u08 high = ADC.Data.High; + if (ADC1.Configuration3.OverrunFlag == 0) { + light_level = (high << 8) | low; +// send_some_command(); + } + ADC1.ControlStatus.EndOfConversion = 0; +} + void main(void) { // Setup clock (External, 16Mhz) CLK.External.HighSpeedExternalEnable = 1; @@ -387,7 +482,6 @@ void main(void) { CLK.Peripheral1.SPI = 0; CLK.Peripheral1.Timer2 = 0; CLK.Peripheral1.Timer4 = 0; - CLK.Peripheral2.AnalogDigitalConvertor = 0; // Setup UART pins RX_PIN_DIR = 0; @@ -401,6 +495,10 @@ void main(void) { PORT_C.CR2.Pin4 = 1; EXTI_CR1.PortC = EXTI_RISING_FALLING; + LIGHT_PIN_DIR = 0; + LIGHT_PIN_CR1 = 0; + LIGHT_PIN_CR2 = 0; + // Setup UART (115200 8N1, with interupt) // 115200 | 9600 | 57600 UART1.CR3 &= ~(UART_CR3_STOP1 | UART_CR3_STOP2); @@ -417,6 +515,19 @@ void main(void) { LED_PIN_CR2 = 0; LED_PIN_OUT = 1; + + // Setup ADC + CLK.Peripheral2.AnalogDigitalConvertor = 1; + ADC1.Configuration2.Alignment = 1; + ADC1.Configuration1.ContinousConversion = 0; + ADC1.ControlStatus.Channel = 0; + ADC1.ControlStatus.Channel = LIGHT_CHANNEL; + ADC1.Configuration1.Prescaler = 7; + ADC1.Configuration2.ExternalTrigger = 0; + ADC1.SchmittDisable.High = 0x3f; + ADC1.SchmittDisable.Low = 0xb3; + ADC1.ControlStatus.Interrupt = 1; + // Setup timer 250ms tick CLK.Peripheral1.Timer1 = 1; const u16 div = 1599;