// #include <avr/io.h> // 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(uint8_t dutyCycle) { // uint16_t value = ICR1 * dutyCycle / 100.0; // OCR1A = value; // } // void pwm_init(); // void pwm_set_frequency(uint16_t frequency); // void pwm_set_duty_cycle(uint8_t dutyCycle); // #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; // } // void i2c_init(); // void i2c_start(); // void i2c_stop(); // void i2c_write(uint8_t data); // uint8_t i2c_read_ack(); // uint8_t i2c_read_nack(); // 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(); // // Инициализируем пины кнопок // 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!"); // 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(500); // 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_set_duty_cycle(0); // } else if (cmd == 0x01) { // pwm_set_duty_cycle(dutyCycle); // } // command = cmd; // } // } // void sendCommand(uint16_t cmd, float value) { // if (cmd != 0x01 && cmd != 0x02) { // если команда изменения параметров // switch (cmd) { // case 0x03: // Увеличить частоту на 25% от текущего. // value = frequency; // value *= 0.25; // break; // case 0x04: // Уменьшить частоту на 20% от текущего. // value = frequency; // value *= 0.2; // break; // case 0x05: // Увеличить скважность на 10% от текущего. // value = dutyCycle; // value *= 0.1; // break; // case 0x06: // Уменьшить скважность на 10% от текущего. // value = dutyCycle; // value *= 0.1; // break; // } // } // uint16_t data = (uint16_t)(value * 16.0); // data |= cmd << 4; // i2c_start(); // i2c_write(PWM_SLAVE_ADDR << 1); // i2c_write(data >> 8); // i2c_write(data & 0xFF); // i2c_stop(); // Serial.print("Sent command: "); // Serial.print(cmd, HEX); // Serial.print(", value: "); // Serial.println(value); // } //VERSION #2 #include <avr/io.h> 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(uint8_t 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 pwm_init(); void pwm_set_frequency(uint16_t frequency); void pwm_set_duty_cycle(uint8_t dutyCycle); void pwm_enable(); void pwm_disable(); #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; } void i2c_init(); void i2c_start(); void i2c_stop(); void i2c_write(uint8_t data); uint8_t i2c_read_ack(); uint8_t i2c_read_nack(); 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); // включение подтягивающего резистора Serial.begin(9600); // Инициализируем Serial монитор Serial.println("PWM Controller started!"); 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(500); 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; } } void sendCommand(uint16_t cmd, float value) { if (cmd != 0x01 && cmd != 0x02) { // если команда изменения параметров switch (cmd) { case 0x03: // Увеличить частоту на 25% от текущего. value = frequency; value *= 0.25; break; case 0x04: // Уменьшить частоту на 20% от текущего. value = frequency; value *= 0.2; break; case 0x05: // Увеличить скважность на 10% от текущего. value = dutyCycle; value *= 0.1; break; case 0x06: // Уменьшить скважность на 10% от текущего. value = dutyCycle; value *= 0.1; break; } } uint16_t data = (uint16_t)(value * 16.0); data |= cmd << 4; i2c_start(); i2c_write(PWM_SLAVE_ADDR << 1); i2c_write(data >> 8); i2c_write(data & 0xFF); i2c_stop(); Serial.print("Sent command: "); Serial.print(cmd, HEX); Serial.print(", value: "); Serial.println(value); // uint16_t data = (uint16_t)(value * 16.0); // data |= cmd << 4; // i2c_start(); // i2c_write(PWM_SLAVE_ADDR << 1); // i2c_write(data >> 8); // Serial.print("Sent byte 1: "); // Serial.println(data >> 8, HEX); // i2c_write(data & 0xFF); // Serial.print("Sent byte 2: "); // Serial.println(data & 0xFF, HEX); // i2c_stop(); // Serial.print("Sent command: "); // Serial.print(cmd, HEX); // Serial.print(", value: "); // Serial.println(value); } //VERSION 3.x // #include <avr/io.h> // #include <util/delay.h> // #include <stdbool.h> // void i2c_init(); // void i2c_start(); // void i2c_stop(); // void i2c_write(uint8_t data); // uint8_t i2c_read_ack(); // uint8_t i2c_read_nack(); // #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; // } // #ifndef PWM_H // #define PWM_H // void pwm_init(); // void pwm_set_frequency(uint16_t frequency); // void pwm_set_duty_cycle(uint8_t dutyCycle); // void pwm_enable(); // void pwm_disable(); // #endif // 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(uint8_t 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); // Выключение ШИМ // } // #define F_CPU 16000000UL // #define I2C_FREQ 100000UL // #define I2C_PRESCALER 1 // #define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) // #define BUTTON_PIN_CNT 6 // 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; // bool is_button_pressed(uint8_t pin); // void process_button_press(uint8_t pin); // void send_command(uint16_t cmd, float value); // int main(void) { // i2c_init(); // pwm_init(); // pwm_enable(); // Включение ШИМ // for (uint8_t i = 0; i < BUTTON_PIN_CNT; i++) { // DDRC &= ~(1 << BUTTON_PIN[i]); // PORTC |= (1 << BUTTON_PIN[i]); // } // Serial.begin(9600); // Инициализируем Serial монитор // Serial.println("PWM Controller started!"); // send_command(0x01, 0.0); // Включить ШИМ при запуске // while (true) { // for (uint8_t i = 0; i < BUTTON_PIN_CNT; i++) { // if (is_button_pressed(BUTTON_PIN[i])) { // process_button_press(BUTTON_PIN[i]); // _delay_ms(500); // } // } // } // } // bool is_button_pressed(uint8_t pin) { // return bit_is_clear(PINC, pin); // } // void process_button_press(uint8_t pin) { // switch (pin) { // case 0: // send_command(0x01, 0.0); // Serial.println("Turn on PWM!"); // break; // case 1: // send_command(0x02, 0.0); // Serial.println("Turn off PWM!"); // break; // case 2: // if (frequency * 1.25 < 10000) { // frequency *= 1.25; // pwm_set_frequency(frequency); // send_command(0x03, 1.25); // Serial.println("Increased frequency!"); // } else { // Serial.println("Maximum frequency reached!"); // } // break; // case 3: // if (frequency * 0.8 > 1) { // frequency *= 0.8; // pwm_set_frequency(frequency); // send_command(0x04, 0.8); // Serial.println("Decreased frequency!"); // } else { // Serial.println("Minimum frequency reached!"); // } // break; // case 4: // if (dutyCycle * 1.1 <= 100) { // dutyCycle *= 1.1; // pwm_set_duty_cycle(dutyCycle); // send_command(0x05, 1.1); // Serial.println("Increased duty cycle!"); // } else { // Serial.println("Maximum duty cycle reached!"); // } // break; // case 5: // if (dutyCycle * 0.9 >= 0) { // dutyCycle *= 0.9; // pwm_set_duty_cycle(dutyCycle); // send_command(0x06, 0.9); // Serial.println("Decreased duty cycle!"); // } else { // Serial.println("Minimum duty cycle reached!"); // } // break; // default: // break; // } // } // void send_command(uint16_t cmd, float value) { // if (cmd != 0x01 && cmd != 0x02) { // если команда изменения параметров // switch (cmd) { // case 0x03: // Увеличить частоту на 25% от текущего. // value = frequency; // value *= 0.25; // break; // case 0x04: // Уменьшить частоту на 20% от текущего. // value = frequency; // value *= 0.2; // break; // case 0x05: // Увеличить скважность на 10% от текущего. // value = dutyCycle; // value *= 0.1; // break; // case 0x06: // Уменьшить скважность на 10% от текущего. // value = dutyCycle; // value *= 0.1; // break; // } // } // uint16_t data = (uint16_t)(value * 16.0); // data |= cmd << 4; // i2c_start(); // i2c_write(PWM_SLAVE_ADDR << 1); // i2c_write(data >> 8); // i2c_write(data & 0xFF); // i2c_stop(); // Serial.print("Sent command: "); // Serial.print(cmd, HEX); // Serial.print(", value: "); // Serial.println(value); // } ///test // #include <Wire.h> // #define PWM_ADDR 9 // Адрес устройства на шине I2C // void setup() { // Wire.begin(); // Serial.begin(9600); // Serial.println("PWM Master device started!"); // Serial.println("I2C connection established"); // } // void loop() { // // Генерация случайного значения ШИМ-сигнала // int pwmValue = random(256); // // Отправка значения по шине I2C на адрес устройства PWM_ADDR // Wire.beginTransmission(PWM_ADDR); // Wire.write(pwmValue); // Wire.endTransmission(); // Serial.print("Sent PWM value: "); // Serial.println(pwmValue); // delay(1000); // Пауза между отправкой нового значения // }