diff --git a/main.c b/main.c new file mode 100644 index 0000000..f8b8ce9 --- /dev/null +++ b/main.c @@ -0,0 +1,215 @@ +#define F_CPU 16000000UL +#define I2C_FREQ 100000UL +#define I2C_PRESCALER 1 +#define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) + +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; + +bool pwm_enabled = true; +float pwm_frequency = 1000.0; +float pwm_duty_cycle = 0.5; + + +void pwm_enable() { + pwm_enabled = true; + pwm_check_state(); +} + +void pwm_disable() { + pwm_enabled = false; + pwm_check_state(); +} + +void setPWMFrequency(float frequency) { + pwm_frequency = frequency; + if (pwm_enabled) { + pwm_set_frequency(pwm_frequency); + } +} + +void setPWMDutyCycle(float duty_cycle) { + pwm_duty_cycle = duty_cycle; + if (pwm_enabled) { + pwm_set_duty_cycle(pwm_duty_cycle); + } +} + + +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); +} + +void increaseFrequency() { + setPWMFrequency(pwm_frequency * 1.25); + sendCommand(0x03, pwm_frequency); +} + +void decreaseFrequency() { + setPWMFrequency(pwm_frequency * 0.8); + sendCommand(0x04, pwm_frequency); +} + + +void increaseDutyCycle() { + if (pwm_duty_cycle < 0.9) { + setPWMDutyCycle(pwm_duty_cycle + 0.1); + sendCommand(0x05, pwm_duty_cycle); + } else { + Serial.println("Maximum duty cycle reached!"); + } +} + +void decreaseDutyCycle() { + if (pwm_duty_cycle > 0.1) { + setPWMDutyCycle(pwm_duty_cycle - 0.1); + sendCommand(0x06, pwm_duty_cycle); + } 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(1000); + 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); +} + + +// 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); + + 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(value); + 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 diff --git a/main.cpp b/main.cpp deleted file mode 100644 index fbfbb6e..0000000 --- a/main.cpp +++ /dev/null @@ -1,165 +0,0 @@ - -#define F_CPU 16000000UL -#define I2C_FREQ 100000UL -#define I2C_PRESCALER 1 -#define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) - -void i2c_init() { - TWBR = I2C_BITRATE; -} - -void i2c_start() { - // отправляем START bit - TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); - - // ожидаем пока START bit будет успешно отправлен - while (!(TWCR & (1 << TWINT))); -} - -void i2c_stop() { - // отправляем STOP bit - TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); - - // ожидаем пока STOP bit будет успешно отправлен - while (TWCR & (1 << TWSTO)); -} - -void i2c_write(uint8_t data) { - // загружаем данные в регистр TWDR - TWDR = data; - - // отправляем данные - TWCR = (1 << TWINT) | (1 << TWEN); - - // ожидаем пока данные будут успешно отправлены - while (!(TWCR & (1 << TWINT))); -} - -uint8_t i2c_read_ack() { - // разрешаем отправку ACK после прочтения байта - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); - - // ожидаем пока данные будут успешно прочитаны - while (!(TWCR & (1 << TWINT))); - - // возвращаем прочитанный байт - return TWDR; -} - -uint8_t i2c_read_nack() { - // запрещаем отправку ACK после прочтения байта - TWCR = (1 << TWINT) | (1 << TWEN); - - // ожидаем пока данные будут успешно прочитаны - while (!(TWCR & (1 << TWINT))); - - // возвращаем прочитанный байт - return TWDR; -} - - - - -const uint8_t BUTTON_PIN[] = {0, 1, 2, 3, 4, 5}; -const uint8_t PWM_SLAVE_ADDR = 9; - -uint16_t command = 0x00; -float frequency = pwm_get_frequency(); -float dutyCycle = pwm_get_duty_cycle(); - - -void setup() { - i2c_init(); - pwm_init(); - pwm_enable(); // Включение ШИМ - - // Инициализируем пины кнопок - DDRC &= ~(1 << PINC0) & ~(1 << PINC1) & ~(1 << PINC2) & ~(1 << PINC3) & ~(1 << PINC4) & ~(1 << PINC5); // подключены кнопки на пинах А0, А1, А2, А3, А4, А5 - PORTC |= (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) | (1 << PINC4) | (1 << PINC5); // включение подтягивающего резистора - - Serial.begin(9600); // Инициализируем Serial монитор - Serial.println("PWM Controller started!"); - Serial.println("PWM on master device initial successful!"); - sendCommand(0x01, 0.0); // Включить ШИМ при запуске -} - -void loop() { - // Обработка нажатий на кнопки - checkButton(0, "Turn on PWM!", 0x01, 0.0); - checkButton(1, "Turn off PWM!", 0x02, 0.0); - checkButton(2, "Increase frequency!", 0x03, 1.25); - checkButton(3, "Decrease frequency!", 0x04, 0.8); - checkButton(4, "Increase duty cycle!", 0x05, 1.1); - checkButton(5, "Decrease duty cycle!", 0x06, 0.9); -} - -void checkButton(uint8_t pin, const char* message, uint16_t cmd, float value) { - if (bit_is_clear(PINC, pin)) { - Serial.println(message); - delay(1000); - - switch(cmd) { - case 0x03: - case 0x04: - frequency *= value; - pwm_set_frequency(frequency); - sendCommand(cmd, value); - break; - - case 0x05: - case 0x06: - dutyCycle *= value; - pwm_set_duty_cycle(dutyCycle); - sendCommand(cmd, value); - break; - - case 0x02: - pwm_disable(); - sendCommand(cmd, value); - pwm_check_state(); - break; - - case 0x01: - pwm_enable(); - sendCommand(cmd, value); - pwm_check_state(); - break; - } - - command = cmd; - } -} - - -void sendCommand(uint16_t cmd, float value) { - // Проверяем, является ли команда изменением частоты или коэффициента заполнения - if (cmd == 0x03 || cmd == 0x04) { - value = pwm_get_frequency(); // Если да, получаем текущее значение частоты - } else if (cmd == 0x05 || cmd == 0x06) { - value = pwm_get_duty_cycle(); // Если да, получаем текущее значение коэффициента заполнения - } - - // Кодируем команду и значение в 16-битное число - uint16_t cmd_value = cmd << 12 | (uint16_t)(value * 16.0f); - - // Отправляем команду через шину I2C - i2c_start(); // Начинаем передачу - i2c_write(PWM_SLAVE_ADDR << 1); // Отправляем адрес устройства - i2c_write(cmd_value >> 8); // Передаем старший байт команды - i2c_write(cmd_value & 0xFF); // Передаем младший байт команды - Serial.println("Packgae send succesfull!"); - i2c_stop(); // Завершаем передачу - - // Выводим информацию о команде в монитор последовательного порта - Serial.print("Sent command: 0x"); - Serial.print(cmd, HEX); - Serial.print(", value: "); - Serial.print(value); - Serial.print(", data bytes: 0x"); - Serial.print(cmd_value >> 8, HEX); - Serial.print(" "); - Serial.println(cmd_value & 0xFF, HEX); -} - - - diff --git a/main2.cpp b/main2.cpp deleted file mode 100644 index 8e471c1..0000000 --- a/main2.cpp +++ /dev/null @@ -1,183 +0,0 @@ - #include - #include - #include - - - - #define I2C_FREQ 100000UL - #define F_CPU 16000000UL - #define I2C_PRESCALER 1 - #define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) - #define I2C_READ 1 - #define I2C_WRITE 0 - - void i2c_init() { - TWBR = I2C_BITRATE; - } - - void i2c_start() { - // отправляем START bit - TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); - - // ожидаем пока START bit будет успешно отправлен - while (!(TWCR & (1 << TWINT))); - } - - void i2c_stop() { - // отправляем STOP bit - TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); - - // ожидаем пока STOP bit будет успешно отправлен - while (TWCR & (1 << TWSTO)); - } - - void i2c_write(uint8_t address, const uint8_t* data, uint8_t length) { - i2c_start(); - // Отправляем адрес устройства с битом записи - TWDR = address << 1 | I2C_WRITE; - TWCR = (1 << TWINT) | (1 << TWEN); - while (!(TWCR & (1 << TWINT))); - - for (uint8_t i = 0; i < length; i++) { - TWDR = data[i]; - TWCR = (1 << TWINT) | (1 << TWEN); - while (!(TWCR & (1 << TWINT))); - } - - i2c_stop(); - } - - void i2c_read(uint8_t address, uint8_t* data, uint8_t length) { - i2c_start(); - - // Отправляем адрес устройства с битом чтения - TWDR = address << 1 | I2C_READ; - TWCR = (1 << TWINT) | (1 << TWEN); - while (!(TWCR & (1 << TWINT))); - - for (uint8_t i = 0; i < length; i++) { - // для всех байт, кроме последнего - отправляем ACK - if (i < length - 1) { - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); - while (!(TWCR & (1 << TWINT))); - data[i] = TWDR; - } - // для последнего байта - отправляем NACK - else { - TWCR = (1 << TWINT) | (1 << TWEN); - while (!(TWCR & (1 << TWINT))); - data[i] = TWDR; - } - } - - i2c_stop(); - } - - - - #define F_CPU 16000000UL - - void pwm_init() { - TCCR1A |= (1 << COM1A1) | (1 << WGM11); // non-inverting mode, Fast PWM (mode 14) - TCCR1B |= (1 << WGM12) | (1 << WGM13) | (1 << CS10); // Fast PWM (mode 14), prescaler = 1 - DDRB |= (1 << PB1); // set pin PB1 as output - } - - void pwm_set_frequency(uint16_t frequency) { - uint16_t prescaler = 1; - uint32_t top = F_CPU / (prescaler * frequency) - 1; - ICR1 = top; - } - - void pwm_set_duty_cycle(float dutyCycle) { - uint16_t value = ICR1 * dutyCycle / 100.0; - OCR1A = value; - } - - void pwm_enable() { - pwm_set_duty_cycle(50); // Начальная скважность - } - - void pwm_disable() { - pwm_set_duty_cycle(0); // Выключение ШИМ - } - - void i2c_init(); - void i2c_start(); - void i2c_stop(); - void i2c_write(uint8_t address, const uint8_t* data, uint8_t length); - void i2c_read(uint8_t address, uint8_t* data, uint8_t length); - - - void pwm_init(); - void pwm_set_frequency(uint16_t frequency); - void pwm_set_duty_cycle(float dutyCycle); - void pwm_enable(); - void pwm_disable(); - - const uint8_t BUTTON_PIN[] = {0, 1, 2, 3, 4, 5}; - const uint8_t PWM_SLAVE_ADDR = 9; - - uint16_t command = 0x00; - float frequency = 1000.0; - float dutyCycle = 50.0; - - void setup() { - i2c_init(); - pwm_init(); - pwm_enable(); // Включение ШИМ - - - // Инициализируем пины кнопок - DDRC &= ~(1 << PINC0) & ~(1 << PINC1) & ~(1 << PINC2) & ~(1 << PINC3) & ~(1 << PINC4) & ~(1 << PINC5); // подключены кнопки на пинах А0, А1, А2, А3, А4, А5 - PORTC |= (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) | (1 << PINC4) | (1 << PINC5); // включение подтягивающего резистора - } - - void loop() { - // Обработка нажатий на кнопки - checkButton(0, 0x01, 0.0); - checkButton(1, 0x02, 0.0); - checkButton(2, 0x03, 1.25); - checkButton(3, 0x04, 0.8); - checkButton(4, 0x05, 1.1); - checkButton(5, 0x06, 0.9); - } - - void checkButton(uint8_t pin, uint16_t cmd, float value) { - if (bit_is_clear(PINC, pin)) { - sendCommand(cmd, value); - if (cmd == 0x03) { - frequency *= value; - pwm_set_frequency(frequency); - } else if (cmd == 0x04) { - frequency *= value; - pwm_set_frequency(frequency); - } else if (cmd == 0x05) { - dutyCycle *= value; - pwm_set_duty_cycle(dutyCycle); - } else if (cmd == 0x06) { - dutyCycle *= value; - pwm_set_duty_cycle(dutyCycle); - } else if (cmd == 0x02) { - pwm_disable(); // Выключение ШИМ - } else if (cmd == 0x01) { - pwm_enable(); // Включение ШИМ - } - command = cmd; - _delay_ms(500); // Задержка для антидребезга - } - } - - void sendCommand(uint16_t cmd, float value) { - uint16_t data = (uint16_t)(value * 16.0); - data |= cmd << 4; - uint8_t buffer[2]; - buffer[0] = data >> 8; - buffer[1] = data & 0xFF; - i2c_write(PWM_SLAVE_ADDR, buffer, 2); - - Serial.print("Command: "); - Serial.print(cmd); - Serial.print(", Value: "); - Serial.println(value, 4); - } \ No newline at end of file diff --git a/slave/slave.cpp b/slave/slave.cpp index 37cd979..74c5bd5 100644 --- a/slave/slave.cpp +++ b/slave/slave.cpp @@ -1,83 +1,82 @@ #include -#define PWM_SLAVE_ADDR 9 +#define SLAVE_ADDRESS 9 void setup() { + Wire.begin(SLAVE_ADDRESS); + Wire.onReceive(receiveCommand); Serial.begin(9600); - Wire.begin(PWM_SLAVE_ADDR); - Wire.onReceive(receiveEvent); + Serial.println("PWM Controller Slave started!"); } void loop() { + // Ваш код в цикле, если необходимо } - - - -void receiveEvent(int byteCount) { - if (Wire.available() >= 2) { - uint16_t data = Wire.read() << 8 | Wire.read(); // Считываем данные из буфера I2C - - uint16_t cmd = data >> 4; // Выделяем команду из принятых данных - float value = ((float)(data & 0x0F)) / 16.0; // Выделяем значение из принятых данных - - Serial.print("Command: "); - Serial.print(cmd); - Serial.print(", Value: "); - Serial.println(value, 4); +void receiveCommand(int byteCount) { + 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); + } + // Добавьте обработку других команд, если необходимо } } +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); +} -// uint16_t cmd_value = cmd << 12 | (uint16_t)(value * 16.0f); -// cmd_value |= cmd; -// i2c_start(); -// i2c_write(PWM_SLAVE_ADDR << 1); -// i2c_write(cmd_value >> 8); // старший байт команды -// i2c_write(cmd_value & 0xFF); // младший байт команды -// i2c_stop(); -// Serial.print("Sent command: 0x"); -// Serial.print(cmd, HEX); -// Serial.print(", value: "); -// Serial.print(value); -// Serial.print(", data bytes: 0x"); -// Serial.print(cmd_value >> 8, HEX); -// Serial.print(" "); -// Serial.println(cmd_value & 0xFF, HEX); +void disablePWM() { + // Ваш код для выключения ШИМ + // Например: analogWrite(PWM_PIN, 0); +} +void setPWMFrequency(float frequency) { + // Ваш код для установки частоты ШИМ +} -// void receiveEvent(int byteCount) { -// if (byteCount > 1) { -// uint16_t cmd_value = (Wire.read() << 8) | Wire.read(); -// uint8_t cmd = cmd_value >> 12; -// float value = (cmd_value & 0xFFF) / 16.0; -// Serial.print("Received command: 0x"); -// Serial.print(cmd, HEX); -// Serial.print(", value: "); -// Serial.print(value); -// Serial.print(", data bytes: 0x"); -// Serial.print(cmd_value >> 8, HEX); -// Serial.print(" "); -// Serial.println(cmd_value & 0xFF, HEX); -// } -// } - - -// void receiveEvent(int byteCount) { -// uint16_t cmd_value = 0; -// if (Wire.available() >= 2) { -// cmd_value = Wire.read() << 8 | Wire.read(); -// uint8_t cmd = cmd_value >> 12; -// uint8_t value = (cmd_value & 0xFFF) / 16.0f; -// Serial.print("Received command: 0x"); -// Serial.print(cmd, HEX); -// Serial.print(", value: "); -// Serial.print(value); -// Serial.print(", data bytes: 0x"); -// Serial.print(cmd_value >> 8, HEX); -// Serial.print(" "); -// Serial.println(cmd_value & 0xFF, HEX); -// } -// } +void setPWMDutyCycle(float dutyCycle) { + // Ваш код для установки коэффициента заполнения ШИМ +} \ No newline at end of file