Уважаемые форумчане, прошу помочь в корректном написании скетча и подключении. К Arduino UNO подключен шаговый двигатель через драйвер DRV8825. Стоят три двухпозиционные кнопки для контроля прижимного механизма и пленки. На кинопроекторе кнопки: Старт, Стоп, Пауза. Так же есть web-камера USB. Цикл таков: Нажата кнопка Пуск на проекторе=>(Начало цикла) Опрашиваются цифровые пины контрольных кнопок (каждый раз в начале цикла). Если 6==0 && 5==0 && 4==1 , то цикл запускается, иначе выдается сообщение на PC о неисправности (Ошибка кнопки 1; Ошибка кнопки 2;Ошибка кнопки 3;Ошибка кнопки 1,2;Ошибка кнопки 1,3;Ошибка кнопки 2,3;Ошибка кнопки 1,2,3=>Если условия верны, то двигатель делает один оборот на 360 градусов=>Передается сигнал на PC (нажатие сочетания клавиш shift+p), что инициирует снятие камерой фото=>Задержка на 30ms (Конец цикла). После нажатия кнопки Пуск - цикл должен повторяться 3000раз, после чего поступит сигнал на зуммер. Если нажали кнопку Пауза то контроллер должен ждать пока не будет снова нажата кнопка старт и продолжить с того же повторения цикла на котором остановился. Если любая из 3 кнопок контроля изменила свое состояние, то контроллер должен ждать пока условие не станет снова верным, будет нажата Пауза, а потом снова Старт, и продолжит с того же повторения на котором остановился. Кнопка Стоп останавливает цикл и сбрасывает счетчик количества повторов. Заранее признателен за любую помощь!
Как-то так ... Код (C++): #define PIN_SW_START 6 #define PIN_SW_STOP 5 #define PIN_SW_PAUSE 4 #define PIN_M_STEP 7 #define PIN_M_DIR 8 #define PIN_BEEPER 9 #define N_SW 3 #define SW_BIT_START 0 #define SW_BIT_STOP 1 #define SW_BIT_PAUSE 2 #define SW_PRESSED LOW #define M_STEP_ACTIVE HIGH #define M_DIR_FORWARD HIGH #define M_STEPS_PER_FRAME 360 #define DELAY_M_STEP_US 1 #define DELAY_FRAME_MS 30 #define DELAY_BEEP_MS 500 #define BEEP_FREQ_HZ 4000 #define N_FRAME_COUNT 3000 #define STATE_START 0 #define STATE_CONTINUE 1 #define STATE_WAIT_KEY 2 #define STATE_PAUSE 3 #define STATE_ERROR 4 #define STATE_STOP 5 #define SERIAL_BAUDRATE 9600 uint8_t state = STATE_START; int frame_counter = 0; bool repeat_frame = false; void initStepper() { // initialize DRV8825 // setup dir/step pins pinMode(PIN_M_STEP, OUTPUT); pinMode(PIN_M_DIR, OUTPUT); digitalWrite(PIN_M_STEP, !M_STEP_ACTIVE); digitalWrite(PIN_M_DIR, M_DIR_FORWARD); } void moveFrameForward() { for (uint8_t i=0; i<M_STEPS_PER_FRAME; i++) { digitalWrite(PIN_M_STEP, M_STEP_ACTIVE); digitalWrite(PIN_M_STEP, !M_STEP_ACTIVE); delayMicroseconds(DELAY_M_STEP_US); } } uint8_t getSwitchState() { uint8_t bits; if (SW_PRESSED==digitalRead(PIN_SW_START)) bits |= _BV(SW_BIT_START); if (SW_PRESSED==digitalRead(PIN_SW_STOP)) bits |= _BV(SW_BIT_STOP); if (SW_PRESSED==digitalRead(PIN_SW_PAUSE)) bits |= _BV(SW_BIT_PAUSE); return bits; } void shootFrame() { Keyboard.press(KEY_LEFT_CTRL); Keyboard.press('P'); Keyboard.releaseAll(); delay(DELAY_FRAME_MS); } void beep() { tone(PIN_BEEPER, BEEP_FREQ_HZ, DELAY_BEEP_MS); } void setup() { Serial.begin(SERIAL_BAUDRATE); Keyboard.begin(); initStepper(); pinMode(PIN_BEEPER, OUTPUT); noTone(PIN_BEEPER); } void loop() { uint8_t sw_state = getSwitchState(); switch(state) { case STATE_START: { if (sw_state) { if (sw_state==_BV(SW_BIT_START)) { while (getSwitchState()); // wait for key relese frame_counter = 0; repeat_frame = false; state = STATE_CONTINUE; } else state = STATE_ERROR; } break; } case STATE_CONTINUE: { if (sw_state) { if (sw_state==_BV(SW_BIT_PAUSE)) { while (getSwitchState()); state = STATE_PAUSE; } else if (sw_state==_BV(SW_BIT_STOP)) { while (getSwitchState()); state = STATE_STOP; } { state = STATE_WAIT_KEY; } } else { if (!repeat_frame) moveFrameForward(); shootFrame(); delay(DELAY_FRAME_MS); frame_counter++; if (frame_counter>=N_FRAME_COUNT) { beep(); state = STATE_STOP; } } break; } case STATE_WAIT_KEY: { if (sw_state==_BV(SW_BIT_PAUSE)) { while (getSwitchState()); state = STATE_PAUSE; } break; } case STATE_PAUSE: { if (sw_state==_BV(SW_BIT_START)) { while (getSwitchState()); repeat_frame = true; state = STATE_CONTINUE; } break; } case STATE_ERROR: { Serial.print("Switches jammed: "); for (uint8_t i=0; i<N_SW; i++) { if (sw_state&_BV(i)) { if (i) Serial.print(','); Serial.print(i+1); } Serial.println(); } state = STATE_START; break; } case STATE_STOP: { frame_counter = 0; repeat_frame = false; state = STATE_START; break; } } }
Можно еще антидребезг добавить Код (C++): #define DELAY_DEBOUNCE_MS 100 uint8_t getRawSwitchState() { uint8_t bits; if (SW_PRESSED==digitalRead(PIN_SW_START)) bits |= _BV(SW_BIT_START); if (SW_PRESSED==digitalRead(PIN_SW_STOP)) bits |= _BV(SW_BIT_STOP); if (SW_PRESSED==digitalRead(PIN_SW_PAUSE)) bits |= _BV(SW_BIT_PAUSE); return bits; } uint8_t getSwitchState() { uint8_t bits0, bits1 = getRawSwitchState(); do { bits0 = bits1; delay(DELAY_DEBOUNCE_MS); bits1 = getRawSwitchState(); } while (bits1!=bits0); return bits0; }
Благодарю за столь быструю помощь! Но в описании системы я не достаточно полно описал кнопки (переключатели) . Всего их получается 6. Три на проекторе (Старт, Стоп, Пауза), подключенные к 3,2 пинам, и три кнопки (концевые переключатели) установлены для контроля прижимного механизма и натяжения пленки, они как раз и подключены к пинам 6,5,4. При правильном положении пленки в начале цикла на 6 и 5 пинах low, а на 4 high. Извините за неточное описание.
И сразу ещё уточню про переключатели на проекторе : нажатие на Старт переводит ее только в положение "включено" , Пауза только при включенном Старте (переводится во "включено" /"выключено") , Стоп механически переводит кнопки Старт и Пауза в состояние "выключено" .
Немного изменил код (добавил 3 кнопки контроля натяжения) и попробовал скомпилировать, но неудачно. Вероятно не хочет Keyboard.h работать с Arduino UNO. Вот сам скетч (прошу посмотреть опытным взглядом, не напортачил ли я в нем): Код (C++): #include <Keyboard.h> #define PIN_SW_START 7 #define PIN_SW_STOP 6 #define PIN_SW_PAUSE 5 #define PIN_M_STEP 9 #define PIN_M_DIR 8 #define PIN_BEEPER 13 #define PIN_SW_LOCK 4 // проверка прижима пленки #define PIN_SW_UL 3 // проверка натяжения на верхней петле #define PIN_SW_DL 2 // проверка натяжения на верхней петле #define N_SW 3 #define SW_BIT_START 0 #define SW_BIT_STOP 1 #define SW_BIT_PAUSE 2 #define SW_BIT_LOCK 3 #define SW_BIT_UL 4 #define SW_BIT_DL 5 #define SW_PRESSED LOW #define M_STEP_ACTIVE HIGH #define M_DIR_FORWARD HIGH #define M_STEPS_PER_FRAME 360 #define DELAY_M_STEP_US 1 #define DELAY_FRAME_MS 30 #define DELAY_BEEP_MS 500 #define BEEP_FREQ_HZ 4000 #define N_FRAME_COUNT 3000 #define STATE_START 0 #define STATE_CONTINUE 1 #define STATE_WAIT_KEY 2 #define STATE_PAUSE 3 #define STATE_STOP 4 #define STATE_ERRORLOCK 5 #define STATE_ERRORUL 6 #define STATE_ERRORDL 7 #define SERIAL_BAUDRATE 9600 uint8_t state = STATE_START; int frame_counter = 0; bool repeat_frame = false; void initStepper() { // initialize DRV8825 // setup dir/step pins pinMode(PIN_M_STEP, OUTPUT); pinMode(PIN_M_DIR, OUTPUT); digitalWrite(PIN_M_STEP, !M_STEP_ACTIVE); digitalWrite(PIN_M_DIR, M_DIR_FORWARD); } void moveFrameForward() { for (uint8_t i=0; i<M_STEPS_PER_FRAME; i++) { digitalWrite(PIN_M_STEP, M_STEP_ACTIVE); digitalWrite(PIN_M_STEP, !M_STEP_ACTIVE); delayMicroseconds(DELAY_M_STEP_US); } } uint8_t getSwitchState() { uint8_t bits; if (SW_PRESSED==digitalRead(PIN_SW_START)) bits |= _BV(SW_BIT_START); if (SW_PRESSED==digitalRead(PIN_SW_STOP)) bits |= _BV(SW_BIT_STOP); if (SW_PRESSED==digitalRead(PIN_SW_PAUSE)) bits |= _BV(SW_BIT_PAUSE); if (SW_PRESSED==digitalRead(PIN_SW_LOCK)) bits |= _BV(SW_BIT_LOCK); if (SW_PRESSED==digitalRead(PIN_SW_UL)) bits |= _BV(SW_BIT_UL); if (SW_PRESSED==digitalRead(PIN_SW_DL)) bits |= _BV(SW_BIT_DL); return bits; } void shootFrame() { Keyboard.press(KEY_LEFT_CTRL); Keyboard.press('P'); Keyboard.releaseAll(); delay(DELAY_FRAME_MS); } void beep() { tone(PIN_BEEPER, BEEP_FREQ_HZ, DELAY_BEEP_MS); } void setup() { Serial.begin(SERIAL_BAUDRATE); Keyboard.begin(); initStepper(); pinMode(PIN_BEEPER, OUTPUT); noTone(PIN_BEEPER); } void loop() { uint8_t sw_state = getSwitchState(); switch(state) { case STATE_START: { if (sw_state) { if (sw_state==_BV(SW_BIT_START)) { while (getSwitchState()); // wait for key relese frame_counter = 0; repeat_frame = false; state = STATE_CONTINUE; } } break; } case STATE_CONTINUE: { if (sw_state) { if (sw_state==_BV(SW_BIT_PAUSE)) { while (getSwitchState()); state = STATE_PAUSE; } else if (sw_state==_BV(SW_BIT_STOP)) { while (getSwitchState()); state = STATE_STOP; } { state = STATE_WAIT_KEY; } } else { if (!repeat_frame) moveFrameForward(); shootFrame(); delay(DELAY_FRAME_MS); frame_counter++; if (frame_counter>=N_FRAME_COUNT) { beep(); state = STATE_STOP; } } break; } case STATE_WAIT_KEY: { if (sw_state==_BV(SW_BIT_PAUSE)) { while (getSwitchState()); state = STATE_PAUSE; } break; } case STATE_PAUSE: { if (sw_state==_BV(SW_BIT_START)) { while (getSwitchState()); repeat_frame = true; state = STATE_CONTINUE; } break; } case STATE_ERRORLOCK: { Serial.print("The film is not clamed: "); for (uint8_t i=0; i<N_SW; i++) { if (sw_state&_BV(i)) { if (i) Serial.print(','); Serial.print(i+1); } Serial.println(); } state = STATE_CONTINUE; break; } case STATE_ERRORUL: { Serial.print("Upper loop misfeed: "); for (uint8_t i=0; i<N_SW; i++) { if (sw_state&_BV(i)) { if (i) Serial.print(','); Serial.print(i+1); } Serial.println(); } state = STATE_CONTINUE; break; } case STATE_ERRORDL: { Serial.print("Upper loop misfeed: "); for (uint8_t i=0; i<N_SW; i++) { if (sw_state&_BV(i)) { if (i) Serial.print(','); Serial.print(i+1); } Serial.println(); } state = STATE_CONTINUE; break; } case STATE_STOP: { frame_counter = 0; repeat_frame = false; state = STATE_START; break; } } } А вот отчет компилятора: Код (Text): In file included from C:\Users\bryak\OneDrive\Документы\Arduino\OcifrovkaVideo\OcifrovkaVideo.ino:1:0: C:\Users\bryak\OneDrive\Документы\Arduino\libraries\Keyboard\src/Keyboard.h:29:2: warning: #warning "Using legacy HID core (non pluggable)" [-Wcpp] #warning "Using legacy HID core (non pluggable)" ^ C:\Users\bryak\OneDrive\Документы\Arduino\OcifrovkaVideo\OcifrovkaVideo.ino: In function 'void shootFrame()': OcifrovkaVideo:82: error: 'Клавиатура' не найдена. Убедитесь входит ли скетч в код '#include <Keyboard.h>'? OcifrovkaVideo:82: error: 'KEY_LEFT_CTRL' was not declared in this scope C:\Users\bryak\OneDrive\Документы\Arduino\OcifrovkaVideo\OcifrovkaVideo.ino: In function 'void setup()': OcifrovkaVideo:96: error: 'Клавиатура' не найдена. Убедитесь входит ли скетч в код '#include <Keyboard.h>'? exit status 1 'Клавиатура' не найдена. Убедитесь входит ли скетч в код '#include <Keyboard.h>'? Выбирал плату LEonardo - компиляция успешная, но мне надо под UNO...
Возьмите Leonardo / Iskra Neo, это будет проще. Конечно, можно извратиться и с Uno, либо перешить мостовую атмегу и USB, либо на V-USB что-то там наколхозить, но это все IMO лишние сложности. Вам нужен МК с USB, который изначально умеет прикидываться USB HID устройством.
Спасибо за совет, видимо придётся взять Leonardo. А в код, который Вы любезно мне предоставили, я верно добавил три кнопки, не нарушил логику?
Бегло просмотрел код. Нигде нет переходов в новые состояния STATE_ERROR<что-то там>, N_SW осталось старым, хотя кнопок теперь 6, SW_PRESSED для разных кнопок у вас разное, соотв. нужна другая константа (ну либо можно прямо в процедуру прописать уровни).