Compare commits

...

10 Commits

Author SHA1 Message Date
2f7f4906bc zmiana pinu i czasu 2026-03-15 10:35:33 +01:00
cc46c0696b definitions for probe and estop 2025-05-30 20:11:04 +02:00
73c78133ac fix led behevior 2025-05-30 19:54:29 +02:00
74a3ace504 change mcu name for avr-gcc 2025-05-30 18:51:56 +02:00
3261e399ba add diffrent brightness leds 2025-05-30 18:51:22 +02:00
943a92869f add estop trigger indicator 2025-05-30 18:50:13 +02:00
ee136cc840 add external connection check 2025-05-30 07:23:20 +02:00
548cee71f4 test adc external connection 2025-05-29 21:47:21 +02:00
fd658face8 add pwm second channnel 2025-05-29 21:35:58 +02:00
67f4677053 convert working example to new with timer and debounce 2025-05-29 20:18:09 +02:00
8 changed files with 309 additions and 43 deletions

View File

@@ -37,4 +37,6 @@ target_sources(${PROJECT_NAME} PRIVATE
src/main.c src/main.c
src/input_handler.c src/input_handler.c
src/timer_counter.c src/timer_counter.c
src/adc_probe_ext.c
src/led_pwm.c
) )

View File

@@ -2,7 +2,7 @@
set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR avr) set(CMAKE_SYSTEM_PROCESSOR avr)
set(AVR_MCU "ATtiny24") set(AVR_MCU "attiny24")
set(AVR_PROGRAMMER "usbasp") set(AVR_PROGRAMMER "usbasp")
# compiler and linker settings # compiler and linker settings

39
src/adc_probe_ext.c Normal file
View File

@@ -0,0 +1,39 @@
#include <avr/io.h>
#include "adc_probe_ext.h"
void adc_init(void)
{
// Vcc as reference, select ADC2 (MUX = 0b010)
ADMUX = (0 << REFS1) | (0 << REFS0) | // VCC as reference
(0 << ADLAR) | // Right adjust result
(0b010); // ADC2
// Enable ADC, prescaler = 64 (assuming 8 MHz → ADC freq = 125 kHz)
ADCSRA = (1 << ADEN) | // Enable ADC
(1 << ADPS2) | (1 << ADPS1); // Prescaler = 64
}
uint16_t adc_read(uint8_t channel)
{
// Set channel (07), keeping the other bits in ADMUX
ADMUX = (ADMUX & 0xF8) | (channel & 0x07);
ADCSRA |= (1 << ADSC); // Start conversion
while (ADCSRA & (1 << ADSC))
; // Wait for conversion to finish
return ADC; // Return 10-bit result
}
uint8_t is_device_connected(void)
{
uint16_t value = adc_read(2); // ADC2 = PA2
// Zakładamy 5V Vcc → 2.5V = około 512
if (value > 400 && value < 600)
{
return 1; // Podłączone (w granicach tolerancji)
}
return 0; // Odłączone (napięcie bliskie 0 lub 5V)
}

5
src/adc_probe_ext.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
void adc_init(void);
uint16_t adc_read(uint8_t channel);
uint8_t is_device_connected(void);

View File

@@ -8,15 +8,16 @@
#define LED34_SW_DDR DDRA #define LED34_SW_DDR DDRA
#define LED34_SW_PORT PORTA #define LED34_SW_PORT PORTA
#define LED_PWM_PIN PA6 #define LED_PWM1_PIN PA6
#define LED_PWM2_PIN PA5
#define LED_PWM_DDR DDRA #define LED_PWM_DDR DDRA
#define LED_PWM_PORT PORTA #define LED_PWM_PORT PORTA
#define PROBE_OUT_PIN PB1 #define PROBE_OUT_PIN PB0
#define PROBE_OUT_DDR DDRB #define PROBE_OUT_DDR DDRB
#define PROBE_OUT_PORT PORTB #define PROBE_OUT_PORT PORTB
#define ESTOP_OUT_PIN PB0 #define ESTOP_OUT_PIN PB1
#define ESTOP_OUT_DDR DDRB #define ESTOP_OUT_DDR DDRB
#define ESTOP_OUT_PORT PORTB #define ESTOP_OUT_PORT PORTB
@@ -35,3 +36,17 @@
#define PROBE_EXT_PIN PA3 #define PROBE_EXT_PIN PA3
#define PROBE_EXT_DDR DDRA #define PROBE_EXT_DDR DDRA
#define PROBE_EXT_PORT PORTA #define PROBE_EXT_PORT PORTA
#define LED_LEFT_GREEN() (LED12_SW_PORT &= ~(1 << LED12_SW_PIN))
#define LED_LEFT_RED() (LED12_SW_PORT |= (1 << LED12_SW_PIN))
#define LED_RIGHT_GREEN() (LED34_SW_PORT &= ~(1 << LED34_SW_PIN))
#define LED_RIGHT_RED() (LED34_SW_PORT |= (1 << LED34_SW_PIN))
#define LED_GREEN_BRIGHTNESS 2
#define LED_RED_BRIGHTNESS 20
#define SET_PROBE_HEIGHT() (PROBE_OUT_PORT &= ~(1 << PROBE_OUT_PIN))
#define SET_PROBE_LOW() (PROBE_OUT_PORT |= (1 << PROBE_OUT_PIN))
#define SET_ESTOP_HEIGHT() (ESTOP_OUT_PORT &= ~(1 << ESTOP_OUT_PIN))
#define SET_ESTOP_LOW() (ESTOP_OUT_PORT |= (1 << ESTOP_OUT_PIN))

70
src/led_pwm.c Normal file
View File

@@ -0,0 +1,70 @@
#include <avr/io.h>
#include "defs.h"
#include "led_pwm.h"
#define PWM_LEFT OCR1B
#define PWM_RIGHT OCR1A
static void led_pwm_init(void)
{
// Ustaw pin PB1 (OC1A) jako wyjście
LED_PWM_DDR |= (1 << LED_PWM1_PIN) | (1 << LED_PWM2_PIN);
// Fast PWM, 8-bit mode, non-inverting mode
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10); // Clear OC1A on compare match
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // Prescaler 64
PWM_RIGHT = 0;
PWM_LEFT = 0;
}
void led_init(void)
{
// Set pins for LED control as output
LED12_SW_DDR |= (1 << LED12_SW_PIN);
LED34_SW_DDR |= (1 << LED34_SW_PIN);
// Turn on red LEDs initially
LED_LEFT_RED();
LED_RIGHT_RED();
// Initialize PWM for LEDs
led_pwm_init();
}
void led_set_color(led_color_t color, led_side_t side)
{
uint8_t pwm_percent = 0;
if (side == LED_LEFT)
{
if (color == LED_COLOR_GREEN)
{
LED_LEFT_GREEN();
pwm_percent = LED_GREEN_BRIGHTNESS;
}
else
{
LED_LEFT_RED();
pwm_percent = LED_RED_BRIGHTNESS;
}
PWM_LEFT = (pwm_percent * 255UL) / 100; // Set PWM duty cycle for left LED
}
if (side == LED_RIGHT)
{
if (color == LED_COLOR_GREEN)
{
LED_RIGHT_GREEN();
pwm_percent = LED_GREEN_BRIGHTNESS;
}
else
{
LED_RIGHT_RED();
pwm_percent = LED_RED_BRIGHTNESS;
}
PWM_RIGHT = (pwm_percent * 255UL) / 100; // Set PWM duty cycle for right LED
}
}

15
src/led_pwm.h Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
typedef enum {
LED_COLOR_RED,
LED_COLOR_GREEN,
} led_color_t;
typedef enum {
LED_LEFT = 1,
LED_RIGHT = 2,
LED_BOTH = 3,
} led_side_t;
void led_init(void);
void led_set_color(led_color_t color, led_side_t side);

View File

@@ -3,54 +3,174 @@
#include <util/delay.h> #include <util/delay.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "defs.h" #include "defs.h"
#include "input_handler.h"
#include "timer_counter.h"
#include "adc_probe_ext.h"
#include "led_pwm.h"
void led_pwm(void); void led_pwm(void);
void probe_int_on(ButtonKey_t *key);
void probe_int_off(ButtonKey_t *key);
void probe_ext_on(ButtonKey_t *key);
void probe_ext_off(ButtonKey_t *key);
void estop_on(ButtonKey_t *key);
void estop_off(ButtonKey_t *key);
ButtonKey_t probe_int = {
.instance = {1, &PINA, PROBE_INT_PIN},
.state = IDLE,
.last_state = IDLE,
.active_state = GPIO_PIN_SET,
.timer_debounce_on = 10, // 1000 ms
.timer_debounce_off = 10, // 1 ms
.buttonReleased = probe_int_off,
.buttonPressed = probe_int_on,
};
ButtonKey_t probe_ext = {
.instance = {2, &PINA, PROBE_EXT_PIN},
.state = IDLE,
.last_state = IDLE,
.active_state = GPIO_PIN_RESET,
.timer_debounce_on = 10, // 1000 ms
.timer_debounce_off = 10, // 1 ms
.buttonReleased = probe_ext_off,
.buttonPressed = probe_ext_on,
};
ButtonKey_t estop_in = {
.instance = {3, &PINA, ESTOP_IN_PIN},
.state = IDLE,
.last_state = IDLE,
.active_state = GPIO_PIN_RESET,
.timer_debounce_on = 10, // 1 ms
.timer_debounce_off = 10, // 1 ms
.buttonReleased = estop_off,
.buttonPressed = estop_on,
};
ButtonKey_t *inputs[3] = {
&probe_int,
&probe_ext,
&estop_in,
};
uint8_t ext_probe_connected = 0;
uint8_t estop_triggered = 0;
uint8_t blink_state = 0;
uint16_t last_blink_time = 0;
int main(void) int main(void)
{ {
LED12_SW_DDR |= (1 << LED12_SW_PIN); PROBE_OUT_DDR |= (1<< PROBE_OUT_PIN);
LED34_SW_DDR |= (1 << LED34_SW_PIN); ESTOP_OUT_DDR |= (1<< ESTOP_OUT_PIN);
// LED12_SW_PORT |= (1 << LED12_SW_PIN); PROBE_OUT_PORT |= (1<< PROBE_OUT_PIN);
// LED34_SW_PORT |= (1 << LED34_SW_PIN); ESTOP_OUT_PORT |= (1<< ESTOP_OUT_PIN);
led_pwm();
// uint8_t i = 0; led_init();
while (1) timer0_init();
{ adc_init();
if (PINA & (1 << PROBE_INT_PIN))
{
LED12_SW_PORT |= (1 << LED12_SW_PIN);
LED34_SW_PORT |= (1 << LED34_SW_PIN);
}
else
{
LED12_SW_PORT &= ~(1 << LED12_SW_PIN);
LED34_SW_PORT &= ~(1 << LED34_SW_PIN);
}
if (!(PINA & (1 << ESTOP_IN_PIN))) sei(); // Enable global interrupts
{
TCCR1A &= ~(1 << COM1A1); // Wyłącz PWM while (1)
LED_PWM_PORT &= ~(1 << LED_PWM_PIN); {
} if (estop_triggered)
else {
{ uint16_t now = ticks100us(); // Musisz mieć funkcję zwracającą czas w ms, np. z timer0
TCCR1A |= (1 << COM1A1); // Włącz PWM if (now - last_blink_time >= 2000) // 0.5 sekundy
// LED_PWM_PORT |= (1 << LED_PWM_PIN); {
} last_blink_time = now;
} blink_state = !blink_state;
return 0; if (blink_state)
{
led_set_color(LED_COLOR_RED, LED_LEFT);
led_set_color(LED_COLOR_GREEN, LED_RIGHT);
}
else
{
led_set_color(LED_COLOR_GREEN, LED_LEFT);
led_set_color(LED_COLOR_RED, LED_RIGHT);
}
}
}
else if (ext_probe_connected != is_device_connected())
{
ext_probe_connected = is_device_connected();
if (ext_probe_connected)
{
led_set_color(LED_COLOR_RED, LED_RIGHT);
}
else
{
led_set_color(LED_COLOR_GREEN, LED_RIGHT);
}
}
for (uint8_t i = 0; i < sizeof(inputs) / sizeof(inputs[0]); i++)
{
buttonHandler(inputs[i]);
}
}
return 0;
} }
void led_pwm(void)
void probe_int_on(ButtonKey_t *key)
{ {
// Ustaw pin PB1 (OC1A) jako wyjście PROBE_OUT_PORT &= ~(1 << PROBE_OUT_PIN);
LED_PWM_DDR |= (1 << LED_PWM_PIN); led_set_color(LED_COLOR_RED, LED_LEFT);
// Ustaw Timer1 w trybie Fast PWM, 8-bit (WGM13:0 = 0b0101) if (!ext_probe_connected)
TCCR1A = (1 << COM1A1) | (1 << WGM10); // Clear OC1A on compare match {
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // Prescaler 64 led_set_color(LED_COLOR_RED, LED_RIGHT);
}
// Ustaw wartość w rejestrze OCR1A (wypełnienie PWM) }
OCR1A = 2; // 50% wypełnienia (dla 8-bit: 128/255)
void probe_int_off(ButtonKey_t *key)
{
PROBE_OUT_PORT |= (1 << PROBE_OUT_PIN);
if (estop_triggered)
{
estop_triggered = 0; // Reset estop when probe back to normal
led_set_color(LED_COLOR_RED, LED_RIGHT);
}
led_set_color(LED_COLOR_GREEN, LED_LEFT);
if (!ext_probe_connected)
{
led_set_color(LED_COLOR_GREEN, LED_RIGHT);
}
}
void probe_ext_on(ButtonKey_t *key)
{
PROBE_OUT_PORT &= ~(1 << PROBE_OUT_PIN);
led_set_color(LED_COLOR_GREEN, LED_RIGHT);
}
void probe_ext_off(ButtonKey_t *key)
{
PROBE_OUT_PORT |= (1 << PROBE_OUT_PIN);
if (estop_triggered)
{
estop_triggered = 0; // Reset estop when probe back to normal
led_set_color(LED_COLOR_GREEN, LED_LEFT);
}
led_set_color(LED_COLOR_RED, LED_RIGHT);
}
void estop_on(ButtonKey_t *key)
{
ESTOP_OUT_PORT &= ~(1 << ESTOP_OUT_PIN);
estop_triggered = 1;
}
void estop_off(ButtonKey_t *key)
{
ESTOP_OUT_PORT |= (1 << ESTOP_OUT_PIN);
} }