From f498e9b0cc4c42a62b591cfea70f944516cca43e Mon Sep 17 00:00:00 2001 From: zloihach <72695485+zloihach@users.noreply.github.com> Date: Fri, 23 Jun 2023 13:04:33 +0300 Subject: [PATCH] update --- main.c | 512 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 256 insertions(+), 256 deletions(-) diff --git a/main.c b/main.c index 1b53008..e3c8b14 100644 --- a/main.c +++ b/main.c @@ -1,256 +1,256 @@ -//#define F_CPU 16000000UL -//#define I2C_FREQ 100000UL -//#define I2C_PRESCALER 1 -//#define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) -// -//#include -//#include -//#include -// -//float pwm_frequency = 1.0; -//float pwm_duty_cycle = 0.5; -// -//volatile uint8_t pwm_enabled = 0; -//volatile uint8_t pwm_changed = 0; -// -//void i2c_init() { -// TWBR = I2C_BITRATE; -//} -// -//void i2c_start() { -// TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); -// while (!(TWCR & (1 << TWINT))) -// ; -//} -// -//void i2c_stop() { -// TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); -// while (TWCR & (1 << TWSTO)) -// ; -//} -// -//void i2c_write(uint8_t data) { -// TWDR = data; -// TWCR = (1 << TWINT) | (1 << TWEN); -// while (!(TWCR & (1 << TWINT))) -// ; -//} -// -//uint8_t i2c_read_ack() { -// TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); -// while (!(TWCR & (1 << TWINT))) -// ; -// return TWDR; -//} -// -//uint8_t i2c_read_nack() { -// TWCR = (1 << TWINT) | (1 << TWEN); -// while (!(TWCR & (1 << TWINT))) -// ; -// return TWDR; -//} -// -//const uint8_t PWM_SLAVE_ADDR = 9; -// -//void pwm_enable() { -// pwm_enabled = 1; -// pwm_changed = 1; -//} -// -//void pwm_disable() { -// pwm_enabled = 0; -// pwm_changed = 1; -//} -// -//void setPWMFrequency(float frequency) { -// if (frequency < 1.0 || frequency > 50000.0) { -// return; // Недопустимая частота -// } -// pwm_frequency = frequency; -// pwm_changed = 1; -//} -// -//void setPWMDutyCycle(float duty_cycle) { -// if (duty_cycle < 0.0 || duty_cycle > 1.0) { -// return; // Недопустимый коэффициент заполнения -// } -// pwm_duty_cycle = duty_cycle; -// pwm_changed = 1; -//} -// -//void pwm_check_state() { -// if (pwm_enabled) { -// // Включаем пин ШИМ - реализация зависит от аппаратной платформы -// Serial.print("PWM enabled. Frequency: "); -// Serial.print(pwm_frequency); -// Serial.print(" Hz, duty cycle: "); -// Serial.println(pwm_duty_cycle); -// } else { -// // Выключаем пин ШИМ - реализация зависит от аппаратной платформы -// Serial.println("PWM disabled"); -// } -//} -// -//void pwm_set_frequency(float frequency) { -// // Устанавливаем частоту ШИМ - реализация зависит от аппаратной платформы -// Serial.print("Setting PWM frequency to: "); -// Serial.println(frequency); -//} -// -//void pwm_set_duty_cycle(float duty_cycle) { -// // Устанавливаем коэффициент заполнения ШИМ - реализация зависит от аппаратной платформы -// Serial.print("Setting PWM duty cycle to: "); -// Serial.println(duty_cycle); -//} -// -//void enablePWM() { -// pwm_enable(); -// // Включаем ШИМ -// sendCommand(0x01, 0.0); -//} -// -//void disablePWM() { -// // Выключаем ШИМ -// sendCommand(0x02, 0.0); -// pwm_disable(); -//} -// -//void increaseFrequency() { -// setPWMFrequency(pwm_frequency * 1.25); -// // Выключаем ШИМ, отправляем команду и включаем обратно -// disablePWM(); -// sendCommand(0x03, pwm_frequency); -// enablePWM(); -//} -// -//void decreaseFrequency() { -// setPWMFrequency(pwm_frequency * 0.8); -// // Выключаем ШИМ, отправляем команду и включаем обратно -// disablePWM(); -// sendCommand(0x04, pwm_frequency); -// enablePWM(); -//} -// -//void increaseDutyCycle() { -// if (pwm_duty_cycle < 0.9) { -// setPWMDutyCycle(pwm_duty_cycle * 1.1); -// // Выключаем ШИМ, отправляем команду и включаем обратно -// disablePWM(); -// sendCommand(0x05, pwm_duty_cycle); -// enablePWM(); -// } else { -// Serial.println("Maximum duty cycle reached!"); -// } -//} -// -//void decreaseDutyCycle() { -// if (pwm_duty_cycle > 0.1) { -// setPWMDutyCycle(pwm_duty_cycle*0.9); -// // Выключаем ШИМ, отправляем команду и включаем обратно -// disablePWM(); -// sendCommand(0x06, pwm_duty_cycle); -// enablePWM(); -// } else { -// Serial.println("Minimum duty cycle reached!"); -// } -//} -// -//void checkButton(uint8_t pin, const char* message, void (*command)()) { -// if (bit_is_clear(PINC, pin)) { -// Serial.println(message); -// delay(200); -// command(); -// } -//} -// -//void setup() { -// i2c_init(); -// DDRC &= ~(1 << PINC0) & ~(1 << PINC1) & ~(1 << PINC2) & ~(1 << PINC3) & ~(1 << PINC4) & ~(1 << PINC5); -// PORTC |= (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) | (1 << PINC4) | (1 << PINC5); -// Serial.begin(9600); -// Serial.println("PWM Controller started!"); -// sendCommand(0x01, 0.0); -//} -// -//void loop() { -// checkButton(0, "Turn on PWM!", enablePWM); -// checkButton(1, "Turn off PWM!", disablePWM); -// checkButton(2, "Increase frequency by 25%!", increaseFrequency); -// checkButton(3, "Decrease frequency by 20%!", decreaseFrequency); -// checkButton(4, "Increase duty cycle by 10%!", increaseDutyCycle); -// checkButton(5, "Decrease duty cycle by 10%!", decreaseDutyCycle); -// -// // Обновляем состояние ШИМ, если что-то изменилось -// if (pwm_changed) { -// pwm_changed = 0; -// pwm_check_state(); -// if (pwm_enabled) { -// pwm_set_frequency(pwm_frequency); -// pwm_set_duty_cycle(pwm_duty_cycle); -// } -// } -//} -// -// -//void sendCommand(uint8_t cmd, float value) { -// // Приводим значение к 12 битам для целой части и 4 битам для дробной части -// uint16_t integer_part = (uint16_t)value; -// uint8_t fractional_part = (uint8_t)((value - integer_part) * 16); -// -// // Проверяем, чтобы значение не превышало допустимых границ -// if (integer_part > 0xFFF) { -// integer_part = 0xFFF; -// } -// if (fractional_part > 0xF) { -// fractional_part = 0xF; -// } -// -// // Формируем 4 байта данных для отправки -// uint8_t upper_byte = (integer_part >> 4) & 0xFF; -// uint8_t lower_byte = ((integer_part & 0xF) << 4) | (fractional_part & 0xF); -// -// i2c_start(); -// i2c_write(PWM_SLAVE_ADDR << 1); -// i2c_write(cmd); -// i2c_write(upper_byte); -// i2c_write(lower_byte); -// i2c_stop(); -// -// Serial.print("Sent command: 0x"); -// Serial.print(cmd, HEX); -// Serial.print(", value: "); -// Serial.print(value); -// Serial.print(", cmd value: "); -// Serial.print((integer_part << 4) | fractional_part); -// Serial.print(", data bytes: 0x"); -// Serial.print(upper_byte, HEX); -// Serial.print(" "); -// Serial.println(lower_byte, HEX); -//} -// -// -// -// -//// void sendCommand(uint8_t cmd, float value) { -//// uint16_t cmd_value = ((uint16_t)cmd << 8) | (uint16_t)(value * 16); -//// uint8_t upper_byte = cmd_value >> 8; -//// uint8_t lower_byte = cmd_value & 0xFF; -// -//// i2c_start(); -//// i2c_write(PWM_SLAVE_ADDR << 1); -//// i2c_write(cmd); -//// i2c_write(upper_byte); -//// i2c_write(lower_byte); -//// i2c_stop(); -// -//// Serial.print("Sent command: 0x"); -//// Serial.print(cmd, HEX); -//// Serial.print(", value: "); -//// Serial.print(cmd_value / 16); -//// Serial.print(", cmd value: "); -//// Serial.print(cmd_value); -//// Serial.print(", data bytes: 0x"); -//// Serial.print(upper_byte, HEX); -//// Serial.print(" "); -//// Serial.println(lower_byte, HEX); -//// } \ No newline at end of file +#define F_CPU 16000000UL +#define I2C_FREQ 100000UL +#define I2C_PRESCALER 1 +#define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) + +#include +#include +#include + +float pwm_frequency = 1.0; +float pwm_duty_cycle = 0.5; + +volatile uint8_t pwm_enabled = 0; +volatile uint8_t pwm_changed = 0; + +void i2c_init() { + TWBR = I2C_BITRATE; +} + +void i2c_start() { + TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); + while (!(TWCR & (1 << TWINT))) + ; +} + +void i2c_stop() { + TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); + while (TWCR & (1 << TWSTO)) + ; +} + +void i2c_write(uint8_t data) { + TWDR = data; + TWCR = (1 << TWINT) | (1 << TWEN); + while (!(TWCR & (1 << TWINT))) + ; +} + +uint8_t i2c_read_ack() { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); + while (!(TWCR & (1 << TWINT))) + ; + return TWDR; +} + +uint8_t i2c_read_nack() { + TWCR = (1 << TWINT) | (1 << TWEN); + while (!(TWCR & (1 << TWINT))) + ; + return TWDR; +} + +const uint8_t PWM_SLAVE_ADDR = 9; + +void pwm_enable() { + pwm_enabled = 1; + pwm_changed = 1; +} + +void pwm_disable() { + pwm_enabled = 0; + pwm_changed = 1; +} + +void setPWMFrequency(float frequency) { + if (frequency < 1.0 || frequency > 50000.0) { + return; // Недопустимая частота + } + pwm_frequency = frequency; + pwm_changed = 1; +} + +void setPWMDutyCycle(float duty_cycle) { + if (duty_cycle < 0.0 || duty_cycle > 1.0) { + return; // Недопустимый коэффициент заполнения + } + pwm_duty_cycle = duty_cycle; + pwm_changed = 1; +} + +void pwm_check_state() { + if (pwm_enabled) { + // Включаем пин ШИМ - реализация зависит от аппаратной платформы + Serial.print("PWM enabled. Frequency: "); + Serial.print(pwm_frequency); + Serial.print(" Hz, duty cycle: "); + Serial.println(pwm_duty_cycle); + } else { + // Выключаем пин ШИМ - реализация зависит от аппаратной платформы + Serial.println("PWM disabled"); + } +} + +void pwm_set_frequency(float frequency) { + // Устанавливаем частоту ШИМ - реализация зависит от аппаратной платформы + Serial.print("Setting PWM frequency to: "); + Serial.println(frequency); +} + +void pwm_set_duty_cycle(float duty_cycle) { + // Устанавливаем коэффициент заполнения ШИМ - реализация зависит от аппаратной платформы + Serial.print("Setting PWM duty cycle to: "); + Serial.println(duty_cycle); +} + +void enablePWM() { + pwm_enable(); + // Включаем ШИМ + sendCommand(0x01, 0.0); +} + +void disablePWM() { + // Выключаем ШИМ + sendCommand(0x02, 0.0); + pwm_disable(); +} + +void increaseFrequency() { + setPWMFrequency(pwm_frequency * 1.25); + // Выключаем ШИМ, отправляем команду и включаем обратно + disablePWM(); + sendCommand(0x03, pwm_frequency); + enablePWM(); +} + +void decreaseFrequency() { + setPWMFrequency(pwm_frequency * 0.8); + // Выключаем ШИМ, отправляем команду и включаем обратно + disablePWM(); + sendCommand(0x04, pwm_frequency); + enablePWM(); +} + +void increaseDutyCycle() { + if (pwm_duty_cycle < 0.9) { + setPWMDutyCycle(pwm_duty_cycle * 1.1); + // Выключаем ШИМ, отправляем команду и включаем обратно + disablePWM(); + sendCommand(0x05, pwm_duty_cycle); + enablePWM(); + } else { + Serial.println("Maximum duty cycle reached!"); + } +} + +void decreaseDutyCycle() { + if (pwm_duty_cycle > 0.1) { + setPWMDutyCycle(pwm_duty_cycle*0.9); + // Выключаем ШИМ, отправляем команду и включаем обратно + disablePWM(); + sendCommand(0x06, pwm_duty_cycle); + enablePWM(); + } else { + Serial.println("Minimum duty cycle reached!"); + } +} + +void checkButton(uint8_t pin, const char* message, void (*command)()) { + if (bit_is_clear(PINC, pin)) { + Serial.println(message); + delay(200); + command(); + } +} + +void setup() { + i2c_init(); + DDRC &= ~(1 << PINC0) & ~(1 << PINC1) & ~(1 << PINC2) & ~(1 << PINC3) & ~(1 << PINC4) & ~(1 << PINC5); + PORTC |= (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) | (1 << PINC4) | (1 << PINC5); + Serial.begin(9600); + Serial.println("PWM Controller started!"); + sendCommand(0x01, 0.0); +} + +void loop() { + checkButton(0, "Turn on PWM!", enablePWM); + checkButton(1, "Turn off PWM!", disablePWM); + checkButton(2, "Increase frequency by 25%!", increaseFrequency); + checkButton(3, "Decrease frequency by 20%!", decreaseFrequency); + checkButton(4, "Increase duty cycle by 10%!", increaseDutyCycle); + checkButton(5, "Decrease duty cycle by 10%!", decreaseDutyCycle); + + // Обновляем состояние ШИМ, если что-то изменилось + if (pwm_changed) { + pwm_changed = 0; + pwm_check_state(); + if (pwm_enabled) { + pwm_set_frequency(pwm_frequency); + pwm_set_duty_cycle(pwm_duty_cycle); + } + } +} + + +void sendCommand(uint8_t cmd, float value) { + // Приводим значение к 12 битам для целой части и 4 битам для дробной части + uint16_t integer_part = (uint16_t)value; + uint8_t fractional_part = (uint8_t)((value - integer_part) * 16); + + // Проверяем, чтобы значение не превышало допустимых границ + if (integer_part > 0xFFF) { + integer_part = 0xFFF; + } + if (fractional_part > 0xF) { + fractional_part = 0xF; + } + + // Формируем 4 байта данных для отправки + uint8_t upper_byte = (integer_part >> 4) & 0xFF; + uint8_t lower_byte = ((integer_part & 0xF) << 4) | (fractional_part & 0xF); + + i2c_start(); + i2c_write(PWM_SLAVE_ADDR << 1); + i2c_write(cmd); + i2c_write(upper_byte); + i2c_write(lower_byte); + i2c_stop(); + + Serial.print("Sent command: 0x"); + Serial.print(cmd, HEX); + Serial.print(", value: "); + Serial.print(value); + Serial.print(", cmd value: "); + Serial.print((integer_part << 4) | fractional_part); + Serial.print(", data bytes: 0x"); + Serial.print(upper_byte, HEX); + Serial.print(" "); + Serial.println(lower_byte, HEX); +} + + + + +// void sendCommand(uint8_t cmd, float value) { +// uint16_t cmd_value = ((uint16_t)cmd << 8) | (uint16_t)(value * 16); +// uint8_t upper_byte = cmd_value >> 8; +// uint8_t lower_byte = cmd_value & 0xFF; + +// i2c_start(); +// i2c_write(PWM_SLAVE_ADDR << 1); +// i2c_write(cmd); +// i2c_write(upper_byte); +// i2c_write(lower_byte); +// i2c_stop(); + +// Serial.print("Sent command: 0x"); +// Serial.print(cmd, HEX); +// Serial.print(", value: "); +// Serial.print(cmd_value / 16); +// Serial.print(", cmd value: "); +// Serial.print(cmd_value); +// Serial.print(", data bytes: 0x"); +// Serial.print(upper_byte, HEX); +// Serial.print(" "); +// Serial.println(lower_byte, HEX); +// } \ No newline at end of file