diff --git a/main.c b/main.c index f8b8ce9..909a9f1 100644 --- a/main.c +++ b/main.c @@ -3,6 +3,16 @@ #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; } @@ -42,88 +52,92 @@ uint8_t i2c_read_nack() { const uint8_t PWM_SLAVE_ADDR = 9; -bool pwm_enabled = true; -float pwm_frequency = 1000.0; -float pwm_duty_cycle = 0.5; - - void pwm_enable() { - pwm_enabled = true; - pwm_check_state(); + pwm_enabled = 1; + pwm_changed = 1; } void pwm_disable() { - pwm_enabled = false; - pwm_check_state(); + pwm_enabled = 0; + pwm_changed = 1; } void setPWMFrequency(float frequency) { - pwm_frequency = frequency; - if (pwm_enabled) { - pwm_set_frequency(pwm_frequency); + if (frequency < 1.0 || frequency > 50000.0) { + return; // Недопустимая частота } + pwm_frequency = frequency; + pwm_changed = 1; } void setPWMDutyCycle(float duty_cycle) { - pwm_duty_cycle = duty_cycle; - if (pwm_enabled) { - pwm_set_duty_cycle(pwm_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) { - pwm_set_frequency(pwm_frequency); - pwm_set_duty_cycle(pwm_duty_cycle); + // Включаем пин ШИМ - реализация зависит от аппаратной платформы Serial.print("PWM enabled. Frequency: "); Serial.print(pwm_frequency); Serial.print(" Hz, duty cycle: "); Serial.println(pwm_duty_cycle); } else { - pwm_set_duty_cycle(0.0); + // Выключаем пин ШИМ - реализация зависит от аппаратной платформы Serial.println("PWM disabled"); } } void pwm_set_frequency(float frequency) { - // TODO: Implement PWM frequency setting logic + // Устанавливаем частоту ШИМ - реализация зависит от аппаратной платформы Serial.print("Setting PWM frequency to: "); Serial.println(frequency); } void pwm_set_duty_cycle(float duty_cycle) { - // TODO: Implement PWM duty cycle setting logic + // Устанавливаем коэффициент заполнения ШИМ - реализация зависит от аппаратной платформы Serial.print("Setting PWM duty cycle to: "); Serial.println(duty_cycle); } - void enablePWM() { pwm_enable(); + // Включаем ШИМ sendCommand(0x01, 0.0); } void disablePWM() { - pwm_disable(); + // Выключаем ШИМ 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 + 0.1); + setPWMDutyCycle(pwm_duty_cycle * 1.1); + // Выключаем ШИМ, отправляем команду и включаем обратно + disablePWM(); sendCommand(0x05, pwm_duty_cycle); + enablePWM(); } else { Serial.println("Maximum duty cycle reached!"); } @@ -131,8 +145,11 @@ void increaseDutyCycle() { void decreaseDutyCycle() { if (pwm_duty_cycle > 0.1) { - setPWMDutyCycle(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!"); } @@ -162,38 +179,35 @@ void loop() { 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) { -// 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); -// } - void sendCommand(uint8_t cmd, float value) { - uint16_t cmd_value = (uint16_t)(value * 16); + // Приводим значение к 12 битам для целой части и 4 битам для дробной части + uint16_t integer_part = (uint16_t)value; + uint8_t fractional_part = (uint8_t)((value - integer_part) * 16); - uint8_t upper_byte = cmd_value >> 8; - uint8_t lower_byte = cmd_value & 0xFF; + // Проверяем, чтобы значение не превышало допустимых границ + 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); @@ -207,9 +221,12 @@ void sendCommand(uint8_t cmd, float value) { Serial.print(", value: "); Serial.print(value); Serial.print(", cmd 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); -} \ No newline at end of file +} + + + diff --git a/slave/slave.cpp b/slave/slave.cpp index 74c5bd5..6c89923 100644 --- a/slave/slave.cpp +++ b/slave/slave.cpp @@ -1,82 +1,27 @@ - #include -#define SLAVE_ADDRESS 9 - void setup() { - Wire.begin(SLAVE_ADDRESS); - Wire.onReceive(receiveCommand); + Wire.begin(9); // Устанавливаем адрес слейва + Wire.onReceive(receiveEvent); // Указываем функцию для обработки приема данных Serial.begin(9600); - Serial.println("PWM Controller Slave started!"); } void loop() { - // Ваш код в цикле, если необходимо + // Здесь можно добавить другие действия слейва, если необходимо } -void receiveCommand(int byteCount) { +void receiveEvent(int numBytes) { while (Wire.available()) { - byte cmd = Wire.read(); - if (cmd == 0x01) { - // Включить ШИМ - float dutyCycle = receiveFloat(); - enablePWM(dutyCycle); - // Ваш код, обрабатывающий команду включения ШИМ - Serial.print("Received command: 0x"); - Serial.print(cmd, HEX); - Serial.print(", duty cycle: "); - Serial.println(dutyCycle); - } else if (cmd == 0x02) { - // Выключить ШИМ - disablePWM(); - // Ваш код, обрабатывающий команду выключения ШИМ - Serial.print("Received command: 0x"); - Serial.println(cmd, HEX); - } else if (cmd == 0x03) { - // Установить частоту ШИМ - float frequency = receiveFloat(); - setPWMFrequency(frequency); - // Ваш код, обрабатывающий команду установки частоты ШИМ - Serial.print("Received command: 0x"); - Serial.print(cmd, HEX); - Serial.print(", frequency: "); - Serial.println(frequency); - } else if (cmd == 0x04) { - // Установить коэффициент заполнения ШИМ - float dutyCycle = receiveFloat(); - setPWMDutyCycle(dutyCycle); - // Ваш код, обрабатывающий команду установки коэффициента заполнения ШИМ - Serial.print("Received command: 0x"); - Serial.print(cmd, HEX); - Serial.print(", duty cycle: "); - Serial.println(dutyCycle); - } - // Добавьте обработку других команд, если необходимо + uint8_t cmd = Wire.read(); + uint8_t upper_byte = Wire.read(); + uint8_t lower_byte = Wire.read(); + + uint16_t cmd_value = (upper_byte << 8) | lower_byte; + float value = cmd_value / 16.0; + + Serial.print("Received command: 0x"); + Serial.print(cmd, HEX); + Serial.print(", value: "); + Serial.println(value); } -} - -float receiveFloat() { - uint8_t upperByte = Wire.read(); - uint8_t lowerByte = Wire.read(); - uint16_t cmdValue = (upperByte << 8) | lowerByte; - float value = (float)cmdValue / 16.0; - return value; -} - -void enablePWM(float dutyCycle) { - // Ваш код для включения ШИМ - // Например: analogWrite(PWM_PIN, dutyCycle * 255); -} - -void disablePWM() { - // Ваш код для выключения ШИМ - // Например: analogWrite(PWM_PIN, 0); -} - -void setPWMFrequency(float frequency) { - // Ваш код для установки частоты ШИМ -} - -void setPWMDutyCycle(float dutyCycle) { - // Ваш код для установки коэффициента заполнения ШИМ } \ No newline at end of file