Check drivers individually!!!
// #define DEBUG
#include "FlexPWM.h"
const uint8_t EN = 10; // № вывода Arduino к которому подключены входы драйвера L_EN и R_EN. Можно указать любой вывод Arduino поддерживающий ШИМ.
const uint8_t L_PWM = 7; // № вывода Arduino к которому подключён вход драйвера L_PWM. Можно указать любой вывод Arduino, как цифровой, так и аналоговый.
const uint8_t R_PWM = 8; // № вывода Arduino к которому подключён вход драйвера R_PWM. Можно указать любой вывод Arduino, как цифровой, так и аналоговый.
#define R_IS A6
#define L_IS A7
#define CW_R_IS 58
#define CW_L_IS 30
#define CCW_R_IS 35
#define CCW_L_IS 46
volatile int current_Ris, current_Lis;
uint32_t old_m = 0;
uint16_t tau = 3000;
volatile int aread5, aread6, aread7;
void setup() {
Serial.begin(115200);
pinMode(EN, OUTPUT); // Конфигурируем вывод EN как выход (выход Arduino, вход драйвера)
pinMode(L_PWM, OUTPUT); // Конфигурируем вывод L_PWM как выход (выход Arduino, вход драйвера)
pinMode(R_PWM, OUTPUT); // Конфигурируем вывод R_PWM как выход (выход Arduino, вход драйвера)
pwmInit(16); // ШИМ 16 бит используем на Pin10 (Timer1) 244Hz
// ADC
OCR0A = 0xAF;
TIMSK0 |= 1 << OCIE0A;
ADMUX = 1 << REFS0; // AVCC with external capacitor at AREF pin
ADCSRA = (1 << ADEN) | (1 << ADATE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
ADCSRB = (1 << ADTS1) | (1 << ADTS0); // Timer/Counter0 Compare Match A
// END-SETUP
}
ISR(TIMER0_COMPA_vect) {
static uint8_t n = 5;
ADMUX = ADMUX & 0b11111000 | n;
switch (n) {
case 5: aread7 = ADC; n = 6; current_Lis = RunMiddleArifmLis(aread7); break;
case 6: aread5 = ADC; n = 7; break;
case 7: aread6 = ADC; n = 5; current_Ris = RunMiddleArifmRis(aread6); break;
}
}
// фильтр среднее с буфером R_IS
uint32_t RunMiddleArifmRis(uint32_t newVal) {
#define NUM_Array 8 // порядок фильтра
static uint32_t ret, buff, buffer[NUM_Array];
static uint8_t i;
if (++i >= NUM_Array) {
i = 0;
}
buff += newVal;
buff -= buffer[i];
buffer[i] = newVal;
ret = buff / NUM_Array;
return ret;
}
//
// фильтр среднее с буфером L_IS
uint32_t RunMiddleArifmLis(uint32_t newVal) {
#define NUM_Array 8 // порядок фильтра
static uint32_t ret, buff, buffer[NUM_Array];
static uint8_t i;
if (++i >= NUM_Array) {
i = 0;
}
buff += newVal;
buff -= buffer[i];
buffer[i] = newVal;
ret = buff / NUM_Array;
return ret;
}
//
void loop() {
// Движение вперёд на 50% скорости:
digitalWrite(L_PWM, LOW ); // Устанавливаем логический 0 на входе драйвера L_PWM, значит на выходе драйвера M- будет установлен потенциал S-
digitalWrite(R_PWM, HIGH); // Устанавливаем логическую 1 на входе драйвера R_PWM, значит на выходе драйвера M+ будет установлен потенциал S+
pwmWrite10(32767);
// analogWrite (EN, 127 ); // Устанавливаем 50% ШИМ на входах драйвера L_EN и R_EN, это скорость, можно установить от 0 (0%) до 255 (100%).
old_m = millis();
Serial.println();
Serial.println("Вперёд на 50%");
while (millis() - old_m <= tau)
{
if (millis() % 250 == 0)
{
#ifdef DEBUG
Serial.print("R_IS="); Serial.print(current_Ris);
Serial.print(" L_IS="); Serial.println(current_Lis);
#else
Serial.print("R_IS="); Serial.print(current_Ris * CW_R_IS);
Serial.print(" L_IS="); Serial.println(current_Lis * CW_L_IS);
#endif
}
}
// delay(3000); // Ждём 3 секунды. ШИМ и логические уровни останутся без изменений, значит мотор продолжит вращаться с указанной скоростью и направлением.
// Движение вперёд на 100% скорости:
digitalWrite(L_PWM, LOW ); // Устанавливаем логический 0 на входе драйвера L_PWM, значит на выходе драйвера M- будет установлен потенциал S-
digitalWrite(R_PWM, HIGH); // Устанавливаем логическую 1 на входе драйвера R_PWM, значит на выходе драйвера M+ будет установлен потенциал S+
pwmWrite10(65535);
// analogWrite (EN, 255 ); // Устанавливаем 100% ШИМ на входах драйвера L_EN и R_EN, это скорость. Если устанавливаемое значение 255, то функцию можно заменить на digitalWrite(EN, HIGH);
Serial.println();
Serial.println("Вперёд на 100%");
old_m = millis();
while (millis() - old_m <= tau)
{
if (millis() % 250 == 0)
{
#ifdef DEBUG
Serial.print("R_IS="); Serial.print(current_Ris);
Serial.print(" L_IS="); Serial.println(current_Lis);
#else
Serial.print("R_IS="); Serial.print(current_Ris * CW_R_IS);
Serial.print(" L_IS="); Serial.println(current_Lis * CW_L_IS);
#endif
}
}
// delay(3000); // Ждём 3 секунды. ШИМ и логические уровни останутся без изменений, значит мотор продолжит вращаться с указанной скоростью и направлением.
// Свободное вращение:
digitalWrite(EN, LOW ); // Устанавливаем логический 0 на входах драйвера L_EN и R_EN, значит выходы M+ и M- перейдут в состояние высокого импеданса и мотор будет электрически отключён.
Serial.println();
Serial.println("Свободное вращение");
// pwmWrite10(0);
old_m = millis();
while (millis() - old_m <= tau)
{
if (millis() % 250 == 0)
{
#ifdef DEBUG
Serial.print("R_IS="); Serial.print(current_Ris);
Serial.print(" L_IS="); Serial.println(current_Lis);
#else
Serial.print("R_IS="); Serial.print(current_Ris * CW_R_IS);
Serial.print(" L_IS="); Serial.println(current_Lis * CW_L_IS);
#endif
}
}
// delay(3000); // Ждём 3 секунды. Логические уровни на входах драйвера L_PWM и R_PWM не имеют значения (могут быть любыми).
// Движение назад на 50% скорости:
digitalWrite(L_PWM, HIGH); // Устанавливаем логическую 1 на входе драйвера L_PWM, значит на выходе драйвера M- будет установлен потенциал S+
digitalWrite(R_PWM, LOW ); // Устанавливаем логический 0 на входе драйвера R_PWM, значит на выходе драйвера M+ будет установлен потенциал S-
pwmWrite10(32767);
// analogWrite (EN, 127 ); // Устанавливаем 50% ШИМ на входах драйвера L_EN и R_EN, это скорость, можно установить от 0 (0%) до 255 (100%).
Serial.println();
Serial.println("Назад на 50%");
old_m = millis();
while (millis() - old_m <= tau)
{
if (millis() % 250 == 0)
{
#ifdef DEBUG
Serial.print("R_IS="); Serial.print(current_Ris);
Serial.print(" L_IS="); Serial.println(current_Lis);
#else
Serial.print("R_IS="); Serial.print(current_Ris * CCW_R_IS);
Serial.print(" L_IS="); Serial.println(current_Lis * CCW_L_IS);
#endif
}
}
// delay(3000); // Ждём 3 секунды. ШИМ и логические уровни останутся без изменений, значит мотор продолжит вращаться с указанной скоростью и направлением.
// Движение назад на 100% скорости:
digitalWrite(L_PWM, HIGH); // Устанавливаем логическую 1 на входе драйвера L_PWM, значит на выходе драйвера M- будет установлен потенциал S+
digitalWrite(R_PWM, LOW ); // Устанавливаем логический 0 на входе драйвера R_PWM, значит на выходе драйвера M+ будет установлен потенциал S-
pwmWrite10(65535);
// digitalWrite(EN, HIGH); // Эта функция выполнит те же действия что и функция analogWrite(EN, 255);
Serial.println();
Serial.println("Назад на 100%");
old_m = millis();
while (millis() - old_m <= tau)
{
if (millis() % 250 == 0)
{
#ifdef DEBUG
Serial.print("R_IS="); Serial.print(current_Ris);
Serial.print(" L_IS="); Serial.println(current_Lis);
#else
Serial.print("R_IS="); Serial.print(current_Ris * CCW_R_IS);
Serial.print(" L_IS="); Serial.println(current_Lis * CCW_L_IS);
#endif
}
}
// delay(3000); // Ждём 3 секунды. Логические уровни останутся без изменений, значит мотор продолжит вращаться с указанной скоростью и направлением.
// Торможение с силой 50%:
digitalWrite(L_PWM, HIGH); // Устанавливаем логическую 1, но можно установить и логический 0, главное что бы уровни на входах драйвера L_PWM и R_PWM совпадали.
digitalWrite(R_PWM, HIGH); // Устанавливаем логическую 1, но можно установить и логический 0, главное что бы уровни на входах драйвера L_PWM и R_PWM совпадали.
pwmWrite10(32767);
// analogWrite (EN, 127 ); // Устанавливаем 50% ШИМ на входах драйвера L_EN и R_EN, это сила торможения, можно установить от 0 (0%) до 255 (100%).
Serial.println();
Serial.println("Торможение с силой 50%");
old_m = millis();
while (millis() - old_m <= tau)
{
if (millis() % 250 == 0)
{
#ifdef DEBUG
Serial.print("R_IS="); Serial.print(current_Ris);
Serial.print(" L_IS="); Serial.println(current_Lis);
#else
Serial.print("R_IS="); Serial.print(current_Ris * CW_R_IS);
Serial.print(" L_IS="); Serial.println(current_Lis * CCW_L_IS);
#endif
}
}
// delay(3000);
}
FlexPWM.h
// <a href="https://arduino.ru/forum/programmirovanie/shim-proizvolnogo-razresheniya-na-unonano-328" rel="nofollow">https://arduino.ru/forum/programmirovanie/shim-proizvolnogo-razresheniya-na-unonano-328</a>
/*
Бит Макс Частота контроллера (МГц)
1 2 4 8 16 20
2 3 250 000,0 500 000,0 1 000 000,0 2 000 000,0 4 000 000,0 5 000 000,0
3 7 125 000,0 250 000,0 500 000,0 1 000 000,0 2 000 000,0 2 500 000,0
4 15 62 500,0 125 000,0 250 000,0 500 000,0 1 000 000,0 1 250 000,0
5 31 31 250,0 62 500,0 125 000,0 250 000,0 500 000,0 625 000,0
6 63 15 625,0 31 250,0 62 500,0 125 000,0 250 000,0 312 500,0
7 127 7 812,5 15 625,0 31 250,0 62 500,0 125 000,0 156 250,0
8 255 3 906,3 7 812,5 15 625,0 31 250,0 62 500,0 78 125,0
9 511 1 953,1 3 906,3 7 812,5 15 625,0 31 250,0 39 062,5
10 1 023 976,6 1 953,1 3 906,3 7 812,5 15 625,0 19 531,3
11 2 047 488,3 976,6 1 953,1 3 906,3 7 812,5 9 765,6
12 4 095 244,1 488,3 976,6 1 953,1 3 906,3 4 882,8
13 8 191 122,1 244,1 488,3 976,6 1 953,1 2 441,4
14 16 383 61,0 122,1 244,1 488,3 976,6 1 220,7
15 32 767 30,5 61,0 122,1 244,1 488,3 610,4
16 65 535 15,3 30,5 61,0 122,1 244,1 305,2
*/
#ifndef FlexPWM_h
#define FlexPWM_h
#define __bit(b) (1u << (b))
inline void pwmInit(const int8_t bitRate = 16) {
noInterrupts();
TCCR1A = __bit(WGM11);
TCCR1B = __bit(WGM13) | __bit(WGM12) | __bit(CS10);
TCCR1C = TCNT1 = OCR1A = OCR1B = TIMSK1 = TIFR1 = 0;
ICR1 = (1u << bitRate) - 1u;
interrupts();
}
inline void pwmWrite9(const uint16_t v) {
DDRB |= __bit(PB1);
TCCR1A |= __bit(COM1A1);
OCR1A = v;
}
inline void digitalWrite9(const uint8_t v) {
DDRB |= __bit(PB1);
TCCR1A &= ~__bit(COM1A1);
if (v) PORTB |= __bit(PB1); else PORTB &= ~__bit(PB1);
}
inline void pwmWrite10(const uint16_t v) {
DDRB |= __bit(PB2);
TCCR1A |= __bit(COM1B1);
OCR1B = v;
}
inline void digitalWrite10(const uint8_t v) {
DDRB |= __bit(PB2);
TCCR1A &= ~__bit(COM1B1);
if (v) PORTB |= __bit(PB2); else PORTB &= ~__bit(PB2);
}
#endif // FlexPWM_h