====== Изучение киберфизических устройств ====== ===== Основы электроники ===== * [[electronics|Основы электроники]] * [[http://www.radio-samodel.ru/kontur.html]] - Нужная теория * [[https://phet.colorado.edu/en/simulation/ohms-law]] - модели, симуляторы * [[http://www.intepra.ru/wiki/doku.php?id=electronics#%D1%82%D0%B5%D0%BE%D1%80%D0%B8%D1%8F|Теория]] * [[http://wiki.amperka.ru/%D0%BA%D0%BE%D0%BD%D1%81%D0%BF%D0%B5%D0%BA%D1%82-arduino:%D0%BF%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D1%81%D1%85%D0%B5%D0%BC%D1%8B|Принципиальные схемы]] * [[http://wiki.amperka.ru/%D0%BA%D0%BE%D0%BD%D1%81%D0%BF%D0%B5%D0%BA%D1%82-arduino:%D1%81%D0%B2%D0%B5%D1%82%D0%BE%D0%B4%D0%B8%D0%BE%D0%B4| Расчет сопротивления для подключения светодиода]] * [[http://wiki.amperka.ru/%D0%BA%D0%BE%D0%BD%D1%81%D0%BF%D0%B5%D0%BA%D1%82-arduino:%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%BD%D0%B0%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F|Делитель напряжения (конспект)]] * [[http://wiki.amperka.ru/%D1%81%D1%85%D0%B5%D0%BC%D0%BE%D1%82%D0%B5%D1%85%D0%BD%D0%B8%D0%BA%D0%B0:%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%BD%D0%B0%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F|Делитель напряжения (статья)]] * [[http://wiki.amperka.ru/%D0%BA%D0%BE%D0%BD%D1%81%D0%BF%D0%B5%D0%BA%D1%82-arduino:%D0%BA%D0%BE%D0%BD%D0%B4%D0%B5%D0%BD%D1%81%D0%B0%D1%82%D0%BE%D1%80| Конденсаторы]] * [[https://youtu.be/msJQH9pONKk]] Урок 16. Как работает RC-цепь * [[https://youtu.be/GWfY0My11v8]] - Ёмкостное сопротивление * [[http://wiki.amperka.ru/%D0%BA%D0%BE%D0%BD%D1%81%D0%BF%D0%B5%D0%BA%D1%82-arduino:%D0%B1%D0%B8%D0%BF%D0%BE%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D0%B9-%D1%82%D1%80%D0%B0%D0%BD%D0%B7%D0%B8%D1%81%D1%82%D0%BE%D1%80 | Биполярные транзисторы]] * [[https://habr.com/post/133136/]] - транзисторы; * [[http://hightolow.ru/transistor2.php]] - принцип работы транзисторов, схемы включения; * [[http://robocraft.ru/blog/arduino/529.html]] - ИК-датчик препятствий для Arduino на базе фототранзистора * [[http://shemopedia.ru/tahometr-na-arduino.html]] - Тахометр на Arduino * https://m.habr.com/post/432778/ * [[http://robocraft.ru/blog/arduino/529.html]] ИК-датчик препятствий для Arduino на базе фототранзистора ===== Электроизмерительные приборы на Arduino ===== * [[https://circuitdigest.com/calculators/resistor-color-code-calculator]] - Resistor Color Code Calculator * [[https://circuitdigest.com/calculators/voltage-divider-calculator]] - Voltage Divider Calculator * [[https://circuitdigest.com/calculators/ohms-law-calculator]] - Ohm's Law Calculator * [[https://circuitdigest.com/microcontroller-projects/arduino-wattmeter-to-measure-voltage-current-power-consumption]] - Arduino Wattmeter: Measure Voltage, Current and Power Consumption * [[https://circuitdigest.com/microcontroller-projects/arduino-sound-level-measurement]] - Measure Sound/Noise Level in dB with Microphone and Arduino * [[https://circuitdigest.com/microcontroller-projects/arduino-lc-meter-measure-inductance]] - LC Meter using Arduino: Measuring Inductance and Frequency * [[https://circuitdigest.com/microcontroller-projects/arduino-oscilloscope-code-circuit]] - Arduino Based Real-Time Oscilloscope ([[oscilloscope-code]]) * [[https://circuitdigest.com/microcontroller-projects/raspberry-pi-based-oscilloscope]] * [[https://www.instructables.com/id/3-Channel-Arduino-Oscilloscope-Under-5-/]] Arduino Oscilloscope Under 5 $ - 3 Channel ===== Практические задания ===== === Схемотехника === * [[http://circuits-cloud.com/]] - circuits-cloud * [[http://www.falstad.com/circuit/circuitjs.html]]- исследование и построение электрических схем (для создания своей схемы можно выбрать в меню "Схемы -> Пустая схема") * [[https://github.com/pfalstad/circuitjs1]] - исходный код редактора электрических схем * [[http://www.falstad.com/circuit/circuitjs.html?cct=$+1+0.000005+10.20027730826997+50+5+50%0Ar+496+240+496+320+0+1000%0Ar+496+320+496+432+0+1000%0Aw+496+240+560+240+0%0At+560+432+624+432+0+1+-4.999812386653795+1.0499981238248927e-10+100%0At+560+240+592+240+0+-1+-0.6320548043420962+-0.6760473009654655+100%0Aw+496+432+560+432+0%0Aw+624+416+624+384+0%0Aw+592+256+592+288+0%0Aw+592+224+672+224+0%0Aw+624+448+624+480+0%0Aw+624+480+704+480+0%0Ag+704+480+704+512+0%0Aw+624+384+704+384+0%0Ar+704+384+800+384+0+220%0A162+880+384+800+384+2+default-led+1+0+0+0.01%0Ar+592+288+672+288+0+220%0A162+672+288+768+288+2+default-led+1+0+0+0.01%0AR+672+224+736+224+0+0+40+5+0+0+0.5%0AR+880+384+944+384+0+0+40+5+0+0+0.5%0Ag+768+288+768+320+0%0Ag+240+336+240+400+0%0Aw+400+320+496+320+0%0AS+400+320+336+320+0+0+false+0+2%0Aw+336+336+240+336+0%0AR+336+304+272+304+0+0+40+5+0+0+0.5%0A | Логический пробник]] * [[http://forum.amperka.ru/threads/%D0%9F%D0%BE%D0%BC%D0%BE%D0%B3%D0%B8%D1%82%D0%B5-%D1%81-h-%D0%BC%D0%BE%D1%81%D1%82%D0%BE%D0%BC.4974/]] - собрать схему Н - моста на транзисторах * [[https://ru.wikipedia.org/wiki/H-%D0%BC%D0%BE%D1%81%D1%82]] - Н - мост * [[http://www.falstad.com/circuit/circuitjs.html?cct=$+1+0.000005+10.20027730826997+50+5+50%0At+448+224+528+224+0+-1+4.973606068151249+-1.049738074243578e-10+100%0At+896+224+800+224+0+-1+-0.6328270118075503+-0.659220943551361+100%0At+448+368+528+368+0+1+0.6328270118075549+0.6592209435513317+100%0At+896+368+800+368+0+1+-4.9736060681512155+1.0497360606398775e-10+100%0Aw+528+240+528+272+0%0Aw+528+352+528+320+0%0Aw+528+320+528+272+0%0Aw+800+240+800+272+0%0Aw+800+352+800+320+0%0Aw+528+272+560+272+0%0Aw+528+320+560+320+0%0Aw+800+272+768+272+0%0Aw+800+320+768+320+0%0Ar+560+272+640+272+0+1000%0A162+768+272+640+272+2+default-led+1+0+0+0.01%0A162+640+320+768+320+2+default-led+1+0+0+0.01%0Ar+560+320+640+320+0+1000%0Aw+800+272+800+320+0%0Aw+528+208+528+176+0%0Aw+528+176+656+176+0%0Aw+656+176+800+176+0%0Aw+800+176+800+208+0%0Aw+656+176+656+128+0%0AR+656+128+656+64+0+0+40+5+0+0+0.5%0Aw+528+384+528+416+0%0Aw+528+416+656+416+0%0Aw+656+416+800+416+0%0Aw+800+416+800+384+0%0Aw+656+416+656+448+0%0Ag+656+448+656+480+0%0Ar+896+224+976+224+0+1000%0Ar+896+368+976+368+0+1000%0Ar+448+224+368+224+0+1000%0Ar+448+368+368+368+0+1000%0Aw+368+224+368+288+0%0Aw+368+288+368+368+0%0Aw+976+224+976+288+0%0Aw+976+368+976+288+0%0Aw+368+288+304+288+0%0Aw+976+288+1040+288+0%0Ax+251+237+264+240+4+24+9%0AR+224+272+144+272+0+0+40+5+0+0+0.5%0Ag+1152+304+1248+304+0%0Ax+1077+250+1103+253+4+24+10%0AS+1040+288+1152+288+0+1+false+0+2%0AS+304+288+224+288+0+1+false+0+2%0AR+1152+272+1216+272+0+0+40+5+0+0+0.5%0Ag+224+304+224+352+0%0Ad+768+272+768+176+2+default%0Ad+768+416+768+320+2+default%0Ad+560+416+560+320+2+default%0Ad+560+272+560+176+2+default%0A | Н-мост, модель]] * [[http://arduinoforme.blogspot.com/2016/02/h-bridge.html]] - теория и практика подключения Н-моста к Arduino * [[http://forum.cxem.net/index.php?/topic/104625-%D0%BF%D0%B5%D1%80%D0%B5%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE%D0%BB%D1%8F%D1%80%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D0%B4%D0%B2%D0%B8%D0%B3%D0%B0%D1%82%D0%B5%D0%BB%D1%8F-%D0%BF%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE-%D1%82%D0%BE%D0%BA%D0%B0/&tab=comments#comment-1172699 | обсуждение вариантов управления двигателем на форуме]] * [[https://online-electric.ru/circuitjs/circuitjs.html?cct=$+1+0.000005+11.086722712598126+63+10+62%0A]] - Пустой лист для схемы * [[https://www.tinkercad.com/]] построить модель * [[https://www.tinkercad.com/dashboard?type=circuits&collection=designs]] === Arduino Nano 3.0 распиновка === * [[http://www.prorobot.ru/arduino/nano-v3.php]] ==== Двухканальный модуль управления двигателем HG7881 HG7881CP ==== * [[https://amperkot.ru/msk/catalog/dvuhkanalnyiy_modul_upravleniya_dvigatelem_hg7881_hg7881cp-23934276.html]] * [[https://ru.aliexpress.com/item/10pcs-lot-L9110S-DC-Stepper-Motor-Driver-Board-H-Bridge-L9110-for-arduino-Free-Shipping-Dropshipping/32251090078.html?af=10546&aff_platform=default&cpt=1548686935579&afref=http%253A%252F%252Farduinolab.pw%252Findex.php%252F2017%252F06%252F15%252Fdrajver-kollektornyx-dvigatelej-l9110s-hg7881&cn=42pm1qhjvbsa4t2flcv6r7h14pfg4m4m&dp=v5_42pm1qhjvbsa4t2flcv6r7h14pfg4m4m&itemrewrite=32251090078_32251090078&duration=1.677545&cv=13433332&pvid=191fc30a-2747-4118-bab0-e8c278da89f4&sk=ccfBY4yg&aff_trace_key=75bd404405ae41d38f5b523b6b137924-1548686935579-03022-ccfBY4yg&from=ITEM_DETAIL&to=ITEM_DETAIL&scm=1007.22893.125778.0&olstatus=noneresult&terminal_id=fb89ac74bab94e698339cc42f357df45 | aliexpress]] * [[https://habr.com/ru/post/211999/]] * [[http://arduino-project.net/drajver-dvigatelya-hg7881-arduino/]] * [[http://arduino-project.net/drajver-dvigatelya-hg7881-arduino/]] Двухканальный драйвер двигателя HG7881 и ардуино (управление скоростью вращения двигателем). * [[http://diyprojects.eu/how-to-use-h-bridge-hg7881-with-external-power-supply-and-arduino/]] - How to use H-bridge HG7881 (HG7881CP) module with external power supply and Arduino UNO * [[https://github.com/tangrs/HG7881-Arduino]] **Простой код для управления реверсивным движением двигателей с равномерным ускорением и замедлением (двухканальный драйвер двигателя HG7881)** /** * H-bridge module HG7881CP/HG7881CP example code /** * Create variables to be used to run motor A */ int motorAPin_lA = 5; //Arduino digital 8 is connected to HG7881's A-1A terminal int motorAPin_lB = 9; //Arduino digital 9 is connected to HG7881's A-1B terminal int motorAPin_rA = 6; //Arduino digital 8 is connected to HG7881's A-1A terminal int motorAPin_rB = 10; void setup(){ /** * When program starts set Arduino pinmode for 8 and 9 digital to be OUTPUT * so we can use analogWrite to output values from 0 to 255 (0-5V) (PWM) */ pinMode(motorAPin_lA, OUTPUT); //direction pinMode(motorAPin_lB, OUTPUT); //speed pinMode(motorAPin_rA, OUTPUT); //direction pinMode(motorAPin_rB, OUTPUT); //speed //Serial.begin(9600); } void loop() { //set motor direction to "X" digitalWrite(motorAPin_lA, LOW); digitalWrite(motorAPin_rA, LOW); //start motor and increase speed while spinnning to direction "X" for(int i=150; i<=255; i++){ //motor speed increases while we loop trough //values from 0 to 255 (0V to power supply max voltage) analogWrite(motorAPin_lB, i); analogWrite(motorAPin_rB, i); delay(5); } //wait 1 seconds while motor is running full speed delay( 1000 ); for(int i=0; i<=105; i++){ //motor speed increases while we loop trough //values from 0 to 255 (0V to power supply max voltage) analogWrite(motorAPin_lB, invertOurValue( i ) ); analogWrite(motorAPin_rB, invertOurValue( i ) ); delay(5); } //take 1 second pause, cutting power from motor ( speed pint to 0V ) //so motor can stop (maybe your motor needs more time to spin down) digitalWrite(motorAPin_lB, LOW); digitalWrite(motorAPin_rB, LOW); delay(1000); //start motor and increase speed while spinnning to direction "X" for(int i=150; i<=255; i++){ //motor speed increases while we loop trough //values from 0 to 255 (0V to power supply max voltage) analogWrite(motorAPin_lA, i); analogWrite(motorAPin_rA, i); delay(5); } //wait 1 seconds while motor is running full speed delay( 1000 ); for(int i=0; i<=105; i++){ //motor speed increases while we loop trough //values from 0 to 255 (0V to power supply max voltage) analogWrite(motorAPin_lA, invertOurValue( i ) ); analogWrite(motorAPin_rA, invertOurValue( i ) ); delay(5); } //Serial.println("***"); //take 1 second pause, cutting power from motor ( speed pint to 0V ) digitalWrite(motorAPin_lA, LOW); digitalWrite(motorAPin_rA, LOW); delay(1000); //and now back to top } int invertOurValue(int input) { return 255 - input; } ==== Программа для автоматического отключения двигателя в момент блокировки или перегрузки ==== Кнопка позволяет запустить двигатель после того, как блокировка будет устранена. int analogPin = A1; // аналоговый порт А1 int state = 1; int newState = state; int pin9 = 9; int val = 0; int button = 0; int buttonPin = 4; void setup() { // put your setup code here, to run once: Serial.begin(9600); pinMode(pin9, OUTPUT); digitalWrite(pin9, state); pinMode(buttonPin, INPUT); } void loop() { val = analogRead(analogPin); //val = map(val, 100, 700, 0, 1000); Serial.println(val); if (val > 500) { newState = 0; } if (newState != state) { Serial.println("***"); digitalWrite(pin9,newState); state = newState; } button = digitalRead(buttonPin); if (button == HIGH) { newState = 1; } delay(100); } ==== Управление двигателем постоянного тока посредством драйвера L293D ==== {{:l293d_arduino.png|}} * [[https://github.com/simonmonk/make_action/blob/master/arduino/experiments/full_motor_control/full_motor_control.ino]] * const int enablePin = 11; // (1) const int in1Pin = 10; const int in2Pin = 9; void setup() { // (2) pinMode(enablePin, OUTPUT); pinMode(in1Pin, OUTPUT); pinMode(in2Pin, OUTPUT); Serial.begin(9600); Serial.println("Enter s (stop) or f or r followed by Duty Cycle (0 to 255). E.g. f120"); } void loop() { // (3) if (Serial.available()) { char direction = Serial.read(); // (4) if (direction == 's') { // (5) stop(); // (6) return; } int pwm = Serial.parseInt(); // (7) if (direction == 'f') { // (8) forward(pwm); } else if (direction == 'r') { reverse(pwm); } } } void forward(int pwm) // (9) { digitalWrite(in1Pin, HIGH); digitalWrite(in2Pin, LOW); analogWrite(enablePin, pwm); Serial.print("Forward "); Serial.println(pwm); } void reverse(int pwm) // (10) { digitalWrite(in1Pin, LOW); digitalWrite(in2Pin, HIGH); analogWrite(enablePin, pwm); Serial.print("Reverse "); Serial.println(pwm); } void stop() // (11) { digitalWrite(in1Pin, LOW); digitalWrite(in2Pin, LOW); analogWrite(enablePin, 0); Serial.println("Stop"); } Управление двумя моторами const int enablePinR = 3; // (1) const int in1PinR = 2; const int in2PinR = 4; const int enablePinL = 6; // (1) const int in1PinL = 7; const int in2PinL = 8; void setup() { // (2) pinMode(enablePinR, OUTPUT); pinMode(in1PinR, OUTPUT); pinMode(in2PinR, OUTPUT); pinMode(enablePinL, OUTPUT); pinMode(in1PinL, OUTPUT); pinMode(in2PinL, OUTPUT); Serial.begin(9600); Serial.println("Enter s (stop) or f or r followed by Duty Cycle (0 to 255). E.g. f120"); } void loop() { // (3) if (Serial.available()) { char direction = Serial.read(); // (4) if (direction == 's') { // (5) stopR(); // (6) stopL(); return; } int pwm = Serial.parseInt(); // (7) if (direction == 'f') { // (8) forwardR(pwm); forwardL(pwm); } else if (direction == 'r') { reverseR(pwm); reverseL(pwm); } } } void forwardR(int pwm) // (9) { digitalWrite(in1PinR, HIGH); digitalWrite(in2PinR, LOW); analogWrite(enablePinR, pwm); Serial.print("Forward "); Serial.println(pwm); } void reverseR(int pwm) // (10) { digitalWrite(in1PinR, LOW); digitalWrite(in2PinR, HIGH); analogWrite(enablePinR, pwm); Serial.print("Reverse "); Serial.println(pwm); } void stopR() // (11) { digitalWrite(in1PinR, LOW); digitalWrite(in2PinR, LOW); analogWrite(enablePinR, 0); Serial.println("Stop"); } void forwardL(int pwm) // (9) { digitalWrite(in1PinL, HIGH); digitalWrite(in2PinL, LOW); analogWrite(enablePinL, pwm); Serial.print("Forward "); Serial.println(pwm); } void reverseL(int pwm) // (10) { digitalWrite(in1PinL, LOW); digitalWrite(in2PinL, HIGH); analogWrite(enablePinL, pwm); Serial.print("Reverse "); Serial.println(pwm); } void stopL() // (11) { digitalWrite(in1PinL, LOW); digitalWrite(in2PinL, LOW); analogWrite(enablePinL, 0); Serial.println("Stop"); } ==== Релейный регулятор датчика линии для мобильного робота (L293D) ==== #define PWMA 6 // выходы arduino #define PWMB 3 #define AIN1 7 #define AIN2 8 #define BIN1 2 #define BIN2 4 #define lS 12 #define rS 11 int min_speed = 120; int max_speed = 255; int n_speed = 180; int dif = 170; uint8_t lSState=0; uint8_t rSState=0; //int state; void setup() { /* Настроить все 7 выводов на выходы, идущие к драйверу TB6612FNG */ pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(lS,INPUT); pinMode(rS,INPUT); Serial.begin(9600); } void loop() { lSState = digitalRead(lS); rSState = digitalRead(rS); Serial.println(lSState); Serial.println(rSState); Serial.println(""); if (lSState == 0 && rSState == 0){ goForward(n_speed); } if (lSState == 1 && rSState == 1){ applyBrakes (); } if (lSState == 1 && rSState == 0){ veerRight(n_speed, dif); } if (lSState == 0 && rSState == 1){ veerLeft(n_speed, dif); } delay(1); } void goForward (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void goBackward (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateRight (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateLeft (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void veerLeft (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v -d); } void veerRight (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v -d); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v ); } void applyBrakes () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } ==== Релейный регулятор датчиков линии на драйвере L293D (обновленная версия) ==== #define PWMA 6 // выходы arduino #define PWMB 3 #define AIN1 7 #define AIN2 8 #define BIN1 2 #define BIN2 4 #define lS 12 #define rS 11 int min_speed = 120; int max_speed = 255; int n_speed = 180; int dif = 180; uint8_t lSState; uint8_t rSState; int state; int prevState; int readyState = 0; void resetState(int st){ prevState = state; state = st; } //int state; void setup() { /* Настроить все 7 выводов на выходы, идущие к драйверу TB6612FNG */ pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(lS,INPUT); pinMode(rS,INPUT); Serial.begin(9600); while (readyState == 0) { testSensors(); if (prevState != 11) readyState = 1; delay(1000); } delay(2000); } void testSensors(){ lSState = digitalRead(lS); rSState = digitalRead(rS); //Serial.println(lSState); //Serial.println(rSState); //Serial.println(""); if (lSState == 0 && rSState == 0 ){ resetState(0); //goForward(n_speed); } if (lSState == 1 && rSState == 0 ){ resetState(10); //goForward(n_speed); } // if (current_dist <= dangerous_dist ){ // resetState(1); //applyBrakes (); // } if (lSState == 1 && rSState == 1 ){ //if (readyState == 0) resetState(11); //veerRight(n_speed, dif); } if (lSState == 0 && rSState == 1 ){ resetState(1); //veerLeft(n_speed, dif); } } void loop() { testSensors(); updateMotion(n_speed, dif); // centralLineFollower(); delay(1); } void updateMotion(int sp, int d){ switch ( state ) { case 0: if (prevState == 1) veerLeft(sp, d); else if (prevState == 10) veerRight(sp, d); break; case 1: // Code goForward(sp); break; case 10: // Code goForward(sp); break; case 11: // Code if (prevState == 10) veerRight(sp, d); else if (prevState == 1) veerLeft(sp, d); break; } } void leftLineFollower(){ //goForward(n_speed); //applyBrakes (); //veerRight(n_speed, dif); //veerLeft(n_speed, dif); } void centralLineFollower(){ } void goForward (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void goBackward (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateRight (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateLeft (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void veerLeft (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v -d); } void veerRight (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v -d); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v ); } void applyBrakes () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } ==== Управление питанием посредством кнопки ==== {{:power_arduino.png|}} * http://arduino.ru/forum/apparatnye-voprosy/vklyuchenie-pitaniya-odnoi-knopkoi {{:power_arduino_2.png|}} * https://youtu.be/lwY6NLT0krA ==== Режимы энергосбережения (Sleep Modes) ==== * [[http://www.gaw.ru/html.cgi/txt/doc/micros/avr/arh/mega103_28.htm]] * [[https://sites.google.com/site/vanyambauseslinux/arduino/ispolzovanie-preryvanij-arduino/probuzdenie-arduino-iz-spasego-rezima-po-nazatiu-knopki?authuser=0]] === Ключевые ресурсы === * [[http://robofob.ru/materials/articles/pages/Karpov_mobline1.pdf]] - Карпов В.Э., ПИД-управление в нестрогом изложении. (27 стр. "Управление по энкодерам") * [[https://www.hse.ru/data/2013/06/17/1287016759/%D0%94%D0%B8%D0%BF%D0%BB%D0%BE%D0%BC.doc]] Луцкий В.А. «Исследование адаптивных алгоритмов передвижения шестиногого шагающего робота», Дипломная работа. * ==== Характеристика двигателя постоянного тока Makeblock 81340 180 Optical Encoder Motor ==== * [[https://www.mightyape.co.nz/product/makeblock-81340-180-optical-encoder-motor/26855245]] * [[https://media.digikey.com/pdf/Data%20Sheets/Makeblock%20PDFs/81340_Web.pdf]] * [[https://store.makeblock.com/180-optical-encoder-motor]] * [[https://roboshop.spb.ru/TB6612FNG-module]] - оптимальный для данного мотора драйвер * [[https://www.sparkfun.com/datasheets/Robotics/TB6612FNG.pdf]] * [[http://arduinolab.pw/index.php/2017/07/04/dvuxkanalnyj-drajver-kollektornyx-motorov-tb6612fng/]] * [[https://github.com/Makeblock-official/Makeblock_Electronic_Modules_v2.0_Schematic_File]] - принципиальные электронные схемы * [[http://download.makeblock.com/Me%20Auriga%20%E7%94%B5%E8%B7%AF%E5%9B%BEV1.1%20-%2020160221.pdf]] * [[https://www.instructables.com/id/Advanced-Makeblock-Sensors-DIY/]] ===== Программирование мобильного робота ===== **Шасси Makeblock, двигатель "Makeblock 81340 180 Optical Encoder Motor", драйвер TB6612FNG.** * [[http://digitrode.ru/articles/123-robot-na-osnove-arduino-chast-iii-podklyuchenie-programmirovanie-i-probnyy-pusk.html]] вариант программы для мобильного робота с использованием драйвера TB6612FNG // http://arduinolab.pw/index.php/2017/07/04/dvuxkanalnyj-drajver-kollektornyx-motorov-tb6612fng/ // http://digitrode.ru/articles/123-robot-na-osnove-arduino-chast-iii-podklyuchenie-programmirovanie-i-probnyy-pusk.html #define PWMA 11 // выходы arduino #define PWMB 10 #define AIN1 6 #define AIN2 7 #define BIN1 5 #define BIN2 4 #define STBY 13 void setup() { /* Настроить все 7 выводов на выходы, идущие к драйверу TB6612FNG */ pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(STBY,OUTPUT); } void loop() { startUp(); goForward(); delay(5500); turnAround(); goForward(); delay(5500); turnAround(); goBackward(); delay(5500); rotateLeft(); delay(560); rotateRight(); delay(560); goForward(); delay(3000); applyBrakes(); delay(2000); } /* Определение функций */ /* Опытным путем было выяснено, что при коэффициенте ШИМ равном 233 */ /* для левого двигателя и 255 для правого позволяют роботу */ /* двигаться по прямой на полной скорости. Тесты показали, что робот */ /* совершает 27 оборотов вокруг своей оси в минуту при вращении двигателей */ /* в противоположные стороны при полном заполнении ШИМ. Эта величина */ /* была использована для определения времени, */ /* за которое робот повернется на 90, 180 и 360 градусов. */ void goForward () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,234); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,255); } void goBackward () { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,233); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } void rotateRight () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,255); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } void rotateLeft () { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,255); } void veerLeft () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,190); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,255); } void veerRight () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,190); } void applyBrakes () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } void startUp () { digitalWrite(STBY,HIGH); } void turnAround() { rotateLeft(); delay(1370); } void shutDown () { digitalWrite(STBY,LOW); } ==== Вариант 1.1. Простейший релейный регулятор движения по линии ==== #define PWMA 11 // выходы arduino #define PWMB 10 #define AIN1 6 #define AIN2 7 #define BIN1 5 #define BIN2 4 #define STBY 13 #define lS 9 #define rS 8 int min_speed = 120; int max_speed = 255; int n_speed = 180; int dif = 170; uint8_t lSState=0; uint8_t rSState=0; //int state; void setup() { /* Настроить все 7 выводов на выходы, идущие к драйверу TB6612FNG */ pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(STBY,OUTPUT); pinMode(lS,INPUT); pinMode(rS,INPUT); Serial.begin(9600); startUp(); } void loop() { lSState = digitalRead(lS); rSState = digitalRead(rS); Serial.println(lSState); Serial.println(rSState); Serial.println(""); if (lSState == 0 && rSState == 0){ goForward(n_speed); } if (lSState == 1 && rSState == 1){ applyBrakes (); } if (lSState == 1 && rSState == 0){ veerRight(n_speed, dif); } if (lSState == 0 && rSState == 1){ veerLeft(n_speed, dif); } delay(1); } void goForward (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void goBackward (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateRight (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateLeft (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void veerLeft (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v -d); } void veerRight (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v -d); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v ); } void applyBrakes () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } void startUp () { digitalWrite(STBY,HIGH); } void shutDown () { digitalWrite(STBY,LOW); } ==== Реализация машины состояний при движении по линии ==== #define PWMA 11 // выходы arduino #define PWMB 10 #define AIN1 6 #define AIN2 7 #define BIN1 5 #define BIN2 4 #define STBY 13 #define lS 9 #define rS 8 int min_speed = 120; int max_speed = 255; int n_speed = 200; int dif = 200; uint8_t lSState; uint8_t rSState; int state; int prevState; int readyState = 0; void resetState(int st){ prevState = state; state = st; } //int state; void setup() { /* Настроить все 7 выводов на выходы, идущие к драйверу TB6612FNG */ pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(lS,INPUT); pinMode(rS,INPUT); Serial.begin(9600); while (readyState == 0) { testSensors(); if (prevState != 11) readyState = 1; delay(1000); } delay(2000); startUp(); } void testSensors(){ lSState = digitalRead(lS); rSState = digitalRead(rS); //Serial.println(lSState); //Serial.println(rSState); //Serial.println(""); if (lSState == 0 && rSState == 0 ){ resetState(0); //goForward(n_speed); } if (lSState == 1 && rSState == 0 ){ resetState(10); //goForward(n_speed); } // if (current_dist <= dangerous_dist ){ // resetState(1); //applyBrakes (); // } if (lSState == 1 && rSState == 1 ){ //if (readyState == 0) resetState(11); //veerRight(n_speed, dif); } if (lSState == 0 && rSState == 1 ){ resetState(1); //veerLeft(n_speed, dif); } } void loop() { testSensors(); updateMotion(n_speed, dif); // centralLineFollower(); //delay(1); } void updateMotion(int sp, int d){ switch ( state ) { case 0: if (prevState == 1) //veerLeft(sp, d); veerRight(sp, d); else if (prevState == 10) //veerRight(sp, d); veerLeft(sp, d); break; case 1: // Code goForward(sp); break; case 10: // Code goForward(sp); break; case 11: // Code if (prevState == 10) veerRight(sp, d); else if (prevState == 1) veerLeft(sp, d); break; } } void leftLineFollower(){ //goForward(n_speed); //applyBrakes (); //veerRight(n_speed, dif); //veerLeft(n_speed, dif); } void centralLineFollower(){ } void goForward (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void goBackward (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateRight (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateLeft (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void veerLeft (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v -d); } void veerRight (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v -d); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v ); } void applyBrakes () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } void startUp () { digitalWrite(STBY,HIGH); } void shutDown () { digitalWrite(STBY,LOW); } ==== Реализация машины состояний при движении по линии (Nano ATmega328P Old) ==== #define PWMA 9 // выходы arduino #define PWMB 10 #define AIN1 6 #define AIN2 7 #define BIN1 5 #define BIN2 4 #define STBY 13 #define lS 2 #define rS 3 int min_speed = 120; int max_speed = 255; int n_speed = 200; int dif = 200; uint8_t lSState; uint8_t rSState; int state; int prevState; int readyState = 0; void resetState(int st){ prevState = state; state = st; } //int state; void setup() { /* Настроить все 7 выводов на выходы, идущие к драйверу TB6612FNG */ pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(lS,INPUT); pinMode(rS,INPUT); Serial.begin(9600); while (readyState == 0) { testSensors(); if (prevState != 11) readyState = 1; delay(1000); } delay(2000); startUp(); } void testSensors(){ lSState = digitalRead(lS); rSState = digitalRead(rS); //Serial.println(lSState); //Serial.println(rSState); //Serial.println(""); if (lSState == 0 && rSState == 0 ){ resetState(0); //goForward(n_speed); } if (lSState == 1 && rSState == 0 ){ resetState(10); //goForward(n_speed); } // if (current_dist <= dangerous_dist ){ // resetState(1); //applyBrakes (); // } if (lSState == 1 && rSState == 1 ){ //if (readyState == 0) resetState(11); //veerRight(n_speed, dif); } if (lSState == 0 && rSState == 1 ){ resetState(1); //veerLeft(n_speed, dif); } } void loop() { testSensors(); updateMotion(n_speed, dif); // centralLineFollower(); //delay(1); } void updateMotion(int sp, int d){ switch ( state ) { case 0: if (prevState == 1) //veerLeft(sp, d); veerRight(sp, d); else if (prevState == 10) //veerRight(sp, d); veerLeft(sp, d); break; case 1: // Code goForward(sp); break; case 10: // Code goForward(sp); break; case 11: // Code if (prevState == 10) veerRight(sp, d); else if (prevState == 1) veerLeft(sp, d); break; } } void leftLineFollower(){ //goForward(n_speed); //applyBrakes (); //veerRight(n_speed, dif); //veerLeft(n_speed, dif); } void centralLineFollower(){ } void goForward (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void goBackward (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateRight (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateLeft (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void veerLeft (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v -d); } void veerRight (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v -d); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v ); } void applyBrakes () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } void startUp () { digitalWrite(STBY,HIGH); } void shutDown () { digitalWrite(STBY,LOW); } ==== Вариант 2.1. Простейший релейный регулятор движения по линии + ультразвуковой датчик препятствия (промежуточный вариант, требует доработки) ==== #include #define PWMA 11 // выходы arduino #define PWMB 10 #define AIN1 6 #define AIN2 7 #define BIN1 5 #define BIN2 4 #define STBY 13 #define lS 9 #define rS 8 int distance = 10; int ping_distance = 400; Ping ping = Ping(2); uint32_t previousMillis = 0; uint16_t timePeriod = 50; int min_speed = 120; int max_speed = 255; int n_speed = 220; int dif = 220; uint8_t lSState; uint8_t rSState; int state; int prevState; int readyState = 0; void resetState(int st){ prevState = state; state = st; } //int state; void setup() { /* Настроить все 7 выводов на выходы, идущие к драйверу TB6612FNG */ pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(lS,INPUT); pinMode(rS,INPUT); Serial.begin(9600); while (readyState == 0) { testSensors(); if (prevState != 11) readyState = 1; delay(1000); } delay(2000); startUp(); } /* void checkTimer(){ uint32_t currentMillis = millis(); if (currentMillis - previousMillis >= timePeriod){ Serial.println(millis()); previousMillis = currentMillis; } } */ void testSensors(){ lSState = digitalRead(lS); rSState = digitalRead(rS); //Serial.println(lSState); //Serial.println(rSState); //Serial.println(""); if (lSState == 0 && rSState == 0 ){ resetState(0); //goForward(n_speed); } if (lSState == 1 && rSState == 0 ){ resetState(10); //goForward(n_speed); } // if (current_dist <= dangerous_dist ){ // resetState(1); //applyBrakes (); // } if (lSState == 1 && rSState == 1 ){ //if (readyState == 0) resetState(11); //veerRight(n_speed, dif); } if (lSState == 0 && rSState == 1 ){ resetState(1); //veerLeft(n_speed, dif); } } void ping_fire(){ ping.fire(); //Serial.println("***"); } void loop() { // time ===================== uint32_t currentMillis = millis(); if (currentMillis - previousMillis >= timePeriod){ //Serial.println(millis()); //Serial.println(ping.centimeters()); ping_distance = ping.centimeters(); ping_fire(); previousMillis = currentMillis; } //======================= testSensors(); if (ping_distance > distance){ updateMotion(n_speed, dif); } else { applyBrakes (); } // centralLineFollower(); //delay(1); } void updateMotion(int sp, int d){ switch ( state ) { case 0: if (prevState == 1) //veerLeft(sp, d); veerRight(sp, d); else if (prevState == 10) //veerRight(sp, d); veerLeft(sp, d); break; case 1: // Code goForward(sp); break; case 10: // Code goForward(sp); break; case 11: // Code if (prevState == 10) veerRight(sp, d); else if (prevState == 1) veerLeft(sp, d); break; } } void leftLineFollower(){ //goForward(n_speed); //applyBrakes (); //veerRight(n_speed, dif); //veerLeft(n_speed, dif); } void centralLineFollower(){ } void goForward (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void goBackward (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateRight (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateLeft (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void veerLeft (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v -d); } void veerRight (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v -d); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v ); } void applyBrakes () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } void startUp () { digitalWrite(STBY,HIGH); } void shutDown () { digitalWrite(STBY,LOW); } /* В библиотеке Ping.cpp вместо строки _duration = pulseIn(_pin, HIGH); следует использовать _duration = pulseIn(_pin, HIGH, 40000); */ ==== Вариант 2.2. Простейший релейный регулятор движения по линии + ультразвуковой датчик препятствия (боле-менее работает :-) ==== #include /* */ #define PWMA 11 // выходы arduino #define PWMB 10 #define AIN1 6 #define AIN2 7 #define BIN1 5 #define BIN2 4 #define STBY 13 #define lS 9 #define rS 8 int distance = 10; int ping_distance = 400; Ping ping = Ping(2); uint32_t previousMillis = 0; uint16_t timePeriod = 50; int min_speed = 120; int max_speed = 255; int n_speed = 200; int dif = 200; uint8_t lSState; uint8_t rSState; int state; int prevState; int readyState = 0; int is_obstacle = 0; void updateState(int st){ state = st; } void resetState(int st){ prevState = state; state = st; } //int state; void setup() { /* Настроить все 7 выводов на выходы, идущие к драйверу TB6612FNG */ pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(lS,INPUT); pinMode(rS,INPUT); Serial.begin(9600); while (readyState == 0) { testSensors(); if (prevState != 11) readyState = 1; delay(1000); } delay(2000); startUp(); } /* void checkTimer(){ uint32_t currentMillis = millis(); if (currentMillis - previousMillis >= timePeriod){ Serial.println(millis()); previousMillis = currentMillis; } } */ void testSensors(){ lSState = digitalRead(lS); rSState = digitalRead(rS); //Serial.println(lSState); //Serial.println(rSState); //Serial.println(""); if (lSState == 0 && rSState == 0 ){ //resetState(0); updateState(0); //goForward(n_speed); } if (lSState == 1 && rSState == 0 ){ resetState(10); //goForward(n_speed); } // if (current_dist <= dangerous_dist ){ // resetState(1); //applyBrakes (); // } if (lSState == 1 && rSState == 1 ){ //if (readyState == 0) //resetState(11); updateState(11); //veerRight(n_speed, dif); } if (lSState == 0 && rSState == 1 ){ resetState(1); //veerLeft(n_speed, dif); } } void ping_fire(){ ping.fire(); //Serial.println("***"); } void loop() { // time ===================== uint32_t currentMillis = millis(); if (currentMillis - previousMillis >= timePeriod){ //Serial.println(millis()); //Serial.println(ping.centimeters()); if (ping_distance > distance){ is_obstacle = 0; } else { is_obstacle = 1; } ping_distance = ping.centimeters(); ping_fire(); previousMillis = currentMillis; } //======================= if (is_obstacle != 1){ testSensors(); updateMotion(n_speed, dif); } else { applyBrakes (); } // centralLineFollower(); //delay(1); } void updateMotion(int sp, int d){ switch ( state ) { case 0: if (prevState == 1) //veerLeft(sp, d); veerRight(sp, d); else if (prevState == 10) //veerRight(sp, d); veerLeft(sp, d); break; case 1: // Code goForward(sp); break; case 10: // Code goForward(sp); break; case 11: // Code if (prevState == 10) veerRight(sp, d); else if (prevState == 1) veerLeft(sp, d); break; } } void leftLineFollower(){ //goForward(n_speed); //applyBrakes (); //veerRight(n_speed, dif); //veerLeft(n_speed, dif); } void centralLineFollower(){ } void goForward (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void goBackward (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateRight (int v) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,LOW); digitalWrite (BIN2,HIGH); analogWrite(PWMB,v); } void rotateLeft (int v) { digitalWrite (AIN1,LOW); digitalWrite (AIN2,HIGH); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v); } void veerLeft (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v -d); } void veerRight (int v, int d) { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); analogWrite(PWMA,v -d); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); analogWrite(PWMB,v ); } void applyBrakes () { digitalWrite (AIN1,HIGH); digitalWrite (AIN2,HIGH); analogWrite(PWMA,255); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,HIGH); analogWrite(PWMB,255); } void startUp () { digitalWrite(STBY,HIGH); } void shutDown () { digitalWrite(STBY,LOW); } /* В библиотеке Ping.cpp вместо строки _duration = pulseIn(_pin, HIGH); следует использовать _duration = pulseIn(_pin, HIGH, 40000); */ ==== Простой таймер (прерывание по таймеру) ==== uint32_t previousMillis = 0; uint16_t timePeriod = 1500; void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { uint32_t currentMillis = millis(); if (currentMillis - previousMillis >= timePeriod){ Serial.println(millis()); previousMillis = currentMillis; } } ==== Ультразвуковой датчик ==== * [[http://playground.arduino.cc/Code/Ping]] * [[http://embeddedlab.csuohio.edu/RoboticSwarms/ultrasonic_sensors.html]] * [[http://arduino.ru/forum/programmirovanie/nestabilnaya-rabota-uz-datchika]] - Форум: "Нестабильная работа УЗ датчика" ==== Bluetooth модуль HC-06 ==== * [[https://lesson.iarduino.ru/page/bluetooth-modul-hc-06-podklyuchenie-k-arduino-upravlenie-ustroystvami-s-telefona]] * [[https://arduinomaster.ru/datchiki-arduino/arduino-bluetooth-hc05-hc06/]] * [[http://zelectro.cc/HC-06_bluetooth_module]] * [[http://psenyukov.ru/%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-bluetooth-hc-06-%D0%BA-arduino-%D1%81-%D0%BF%D1%80%D0%BE%D1%88%D0%B8%D0%B2%D0%BA%D0%BE%D0%B9-grbl/]] * [[https://play.google.com/store/apps/details?id=braulio.calle.bluetoothRCcontroller&hl=ru]] - Google Play bluetooth-rc-car * [[https://create.arduino.cc/projecthub/samanfern/bluetooth-controlled-car-d5d9ca]] - Arduino Bluetooth Controlled Car * [[https://tutorial45.com/arduino-bluetooth-rc-car-project/]] - Arduino Bluetooth Controlled Car * [[http://www.ardumotive.com/bluetooth-rc-car.html]] - Arduino Bluetooth Controlled Car * ==== Указатели в C для Ардуино ==== * [[http://mypractic.ru/urok-15-ukazateli-v-c-dlya-arduino-preobrazovanie-raznyx-tipov-dannyx-v-bajty.html]] ==== Принципы программирования оптических энкодеров ==== * [[http://robotosha.ru/arduino/wheel-encoders-dfrobot.html]] ... колесные энкодеры ... (измерение скорости) * [[https://sohabr.net/habr/post/340448/?version=254649]] - как определить угол поворота инкрементального энкодера * [[http://robofob.ru/materials/begin/mEncoder.pdf]] Карпов В.Э. Управление движением робота с использованием энкодеров * [[https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/]] attachInterrupt() * https://playground.arduino.cc/Main/RotaryEncoders * https://forum.arduino.cc/index.php?topic=488275.0 * https://www.allaboutcircuits.com/projects/how-to-use-a-rotary-encoder-in-a-mcu-based-project/ * http://www.bristolwatch.com/arduino/arduino2.htm * http://makeatronics.blogspot.com/2013/02/efficiently-reading-quadrature-with.html * http://mypractic.ru/urok-55-rabota-s-inkrementalnym-enkoderom-v-arduino-biblioteka-encod_er-h.html * http://cxem.net/arduino/arduino8.php * https://www.instructables.com/id/Improved-Arduino-Rotary-Encoder-Reading/ * https://robu.in/run-rotary-encoder-arduino-code/ * https://arduino.stackexchange.com/questions/598/how-precise-can-i-get-arduino-using-rotary-encoders * http://robotosha.ru/robotics/optical-encoders.html * http://robocraft.ru/blog/2965.html * http://robot-kit.ru/product_info.php/info/p811_Modul-datchika-oborotov--yenkoder--RKP-MWES-LM393-.html * [[http://robot-kit.ru/manual/Motor_Wheel_Encoder_Sensor.pdf]] Карпов В.Э. Управление движением роботов с использованием энкодеров * http://easyelectronics.ru/avr-uchebnyj-kurs-inkrementalnyj-enkoder.html * [[http://robofob.ru/materials/articles/pages/avprog.pdf]] Карпов В.Э. Автоматное программирование и робототехника ==== Прерывания по таймеру ==== * [[https://playground.arduino.cc/Code/Timer1/]] :: Timer1 :: !!! * [[https://code.google.com/archive/p/arduino-timerone/downloads]] * [[https://github.com/PaulStoffregen/TimerOne]] * [[https://wm-help.net/lib/b/book/1248084587/6]] * [[https://habr.com/ru/post/337430/]] !!! * [[http://arduino.ru/forum/programmirovanie/preryvaniya-po-taimeru]] * [[https://all-arduino.ru/arduino-dlya-nachinayushhih-urok-14-preryvaniya/]] * [[http://robotosha.ru/arduino/multitasking-and-interrupts-arduino.html]] ==== О прерываниях ==== * https://radioprog.ru/post/499 * https://all-arduino.ru/programmirovanie-arduino/attachinterrupt/ * https://m.habr.com/ru/post/253213/ * https://arduinomaster.ru/program/preryvaniya-arduino-attachinterrupt/ * http://robotosha.ru/arduino/arduino-interrupts.html ==== Дополнительные материалы по управлению двигателями... ==== * [[https://sohabr.net/habr/post/280486/#comment_8837922]] * https://sohabr.net/habr/post/277671/ * https://habr.com/ru/post/260783/ * https://sohabr.net/habr/post/340448/?version=254649 * ==== АЦП ==== [[http://codius.ru/articles/Arduino_%D1%83%D1%81%D0%BA%D0%BE%D1%80%D1%8F%D0%B5%D0%BC_%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%83_%D0%BF%D0%BB%D0%B0%D1%82%D1%8B_%D0%A7%D0%B0%D1%81%D1%82%D1%8C_2_%D0%90%D0%BD%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE_%D1%86%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%BE%D0%B9_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C_%D0%90%D0%A6%D0%9F_%D0%B8_analogRead|АЦП]] * [[http://robotosha.ru/arduino/analog-measurements-arduino.html]] - Аналоговые измерения ==== Простейший аналоговый пробник ==== int analogPin = A1; // аналоговый порт А1 int val = 0; void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { val = analogRead(analogPin); Serial.println(val); delay(100); } ==== "Аналоговый графопостроитель" ==== const uint8_t analogPin1 = A1; const uint8_t analogPin2 = A2; void setup() { pinMode(analogPin1,INPUT); pinMode(analogPin2,INPUT); Serial.begin(9600); } void loop() { int val1 = analogRead(analogPin1); int val2 = analogRead(analogPin2); Serial.print(val1); Serial.print(" "); Serial.println(val2); delay(50); } ==== Простейший цифровой пробник ==== int dPinInput = 7; int dPinOutput = 8; int val = 0; void setup() { // put your setup code here, to run once: pinMode(dPinInput, INPUT); pinMode(dPinOutput, OUTPUT); Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: val = digitalRead(dPinInput); Serial.println(val); digitalWrite(dPinOutput, val); delay(100); } ==== Фильтр аналогового сигнала для регистрации света ==== При освещении фоторезистора светодиодным фонарем, график уровня освещенности получается зубчатым (импульсный свет), для сглаживания использован следующий программный фильтр. int analogPin = A1; // аналоговый порт А1 int val = 0; // variable to store the value read void setup() { Serial.begin(9600); // setup serial } void loop() { int sv = 0; for (int i = 0; i <= 100;i++){ val = analogRead(analogPin); // read the input pin val = map(val, 10, 500, 0, 100); sv += val; delay(2); } Serial.println(sv/100); //Serial.println(sv*5.0/1023); // напряжение в вольтах //Serial.println("------------------"); delay(1); } ==== Дребезг кнопок ==== int counter = 0; int bPin = 2; bool state = 1; // void setup() { // put your setup code here, to run once: pinMode(bPin, INPUT_PULLUP); Serial.begin(9600); } void loop() { bool b_state = digitalRead(bPin); if (state != b_state){ counter ++; Serial.println(counter); state = b_state; delay(20); } //Serial.println(b_state); //delay(5); } ==== Обработка различных состояний кнопки (вариант 1). ==== int counter = 0; int bPin = 2; int ledPin = 10; bool state = 1; // int val = 0; void setup() { // put your setup code here, to run once: pinMode(bPin, INPUT_PULLUP); pinMode(ledPin, OUTPUT); Serial.begin(9600); } void loop() { bool b_state = digitalRead(bPin); if (state != b_state) { counter ++; //val = !b_state; state = b_state; delay(20); val = counter % 6; } switch (val) { case 0: digitalWrite(ledPin, LOW); break; case 2: analogWrite(ledPin, 70); break; case 4: digitalWrite(ledPin, HIGH); break; //default: } delay(50); } ==== Обработка различных состояний кнопки (вариант 2). ==== int bPin = 2; int ledPin = 5; int counter = 0; int b_state = 1; void setup() { // put your setup code here, to run once: pinMode(bPin, INPUT_PULLUP); pinMode(ledPin, OUTPUT); Serial.begin(9600); Serial.println("HELLO!"); } void loop() { int val = digitalRead(bPin); if (b_state != val){ if (val == 0){ counter ++; } b_state = val; //Serial.println(counter % 2); int r = counter % 3; delay(10); switch(r){ case 0: analogWrite(ledPin,0); break; case 1: analogWrite(ledPin,50); break; case 2: analogWrite(ledPin,255); break; } } } ==== Многозадачность на Arduino. Таймер на различные состояния. ==== //http://robotosha.ru/arduino/multi-tasking-arduino.html // Эти переменные хранят временной шаблон для интервалов мигания // и текущее состояние светодиода int ledPin = 13; // номер пина со светодиодом int ledState = 0; // состояние светодиода // последний момент времени, когда состояние светодиода изменялось uint32_t previousMillis = 0; uint16_t OnTime = 250; // длительность свечения светодиода (в миллисекундах) uint16_t OffTime = 750; // светодиод не горит (в миллисекундах) void setup() { // устанавливаем цифровой пин со светодиодом как ВЫХОД pinMode(ledPin, OUTPUT); } void loop() { // выясняем не настал ли момент сменить состояние светодиода uint32_t currentMillis = millis(); // текущее время в миллисекундах // если светодиод включен и светится больше чем надо if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // выключаем previousMillis = currentMillis; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // выключаем previousMillis = currentMillis ; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } } ==== Многозадачность на Arduino. Создание класса. ==== // http://robotosha.ru/arduino/multi-tasking-arduino.html class Flasher { // Переменные - члены класса // Инициализируются при запуске int ledPin; // номер пина со светодиодом long OnTime; // время включения в миллисекундах long OffTime; // время, когда светодиод выключен // Текущее состояние int ledState; // состояние ВКЛ/ВЫКЛ unsigned long previousMillis; // последний момент смены состояния // Конструктор создает экземпляр Flasher и инициализирует // переменные-члены класса и состояние public: Flasher(int pin, long on, long off) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = LOW; previousMillis = 0; } void Update() { // выясняем не настал ли момент сменить состояние светодиода unsigned long currentMillis = millis(); // текущее время в миллисекундах if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // выключаем previousMillis = currentMillis; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // выключаем previousMillis = currentMillis ; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } } }; Flasher led1(11, 100, 400); Flasher led2(12, 350, 350); Flasher led3(13, 300, 700); void setup() { } void loop() { led1.Update(); led2.Update(); led3.Update(); } ==== Модификация класса. Визуализация процессов. ==== Все достаточно неплохо, однако наблюдается дрейфующая рассинхронизация процессов. // визуализация процессов (модификация кода http://robotosha.ru/arduino/multi-tasking-arduino.html) //const uint8_t analogPin1 = A1; //const uint8_t analogPin2 = A2; uint8_t val2; uint8_t val3; class Flasher { // Переменные - члены класса // Инициализируются при запуске int ledPin; // номер пина со светодиодом long OnTime; // время включения в миллисекундах long OffTime; // время, когда светодиод выключен // Текущее состояние uint8_t ledState; // состояние ВКЛ/ВЫКЛ unsigned long previousMillis; // последний момент смены состояния // Конструктор создает экземпляр Flasher и инициализирует // переменные-члены класса и состояние public: Flasher(int pin, long on, long off) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = LOW; previousMillis = 0; } void Update() { // выясняем не настал ли момент сменить состояние светодиода unsigned long currentMillis = millis(); // текущее время в миллисекундах if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // выключаем previousMillis = currentMillis; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // выключаем previousMillis = currentMillis ; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } } uint8_t getState(){ return ledState; } }; //Flasher led1(11, 100, 400); Flasher led2(12, 200, 200); Flasher led3(13, 400, 400); void setup() { Serial.begin(9600); } void loop() { //led1.Update(); led2.Update(); val2 = led2.getState(); led3.Update(); val3 = led3.getState(); Serial.print(val2 + 2); Serial.print(" "); Serial.println(val3); // для Serial Plotter } // Serial.print(val1); Serial.print(" "); Serial.println(val2); ==== Измененный алгоритм класса синхронных процессов с визуализацией ==== Синхронизация восстановлена... class Flasher { // Переменные - члены класса // Инициализируются при запуске uint8_t ledPin; // номер пина со светодиодом uint16_t OnTime; // время включения в миллисекундах uint16_t OffTime; // время, когда светодиод выключен // Текущее состояние uint8_t ledState; // изначальное состояние светодиода uint8_t realLedState; // текущее состояние светодиода //uint32_t currentTime; // текущее время uint32_t summTime; // расчетное время свечения // Конструктор создает экземпляр Flasher и инициализирует // переменные-члены класса и состояние public: Flasher(uint8_t pin, uint16_t on, uint16_t off, uint8_t st) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = st; realLedState = st; //currentTime = 0; //currentPeriod = 0; summTime = 0; } void Update(){ uint32_t currentMillis = millis(); // текущее время в миллисекундах if(ledState == HIGH) { if (currentMillis <= (OnTime + summTime)) { realLedState = ledState; digitalWrite(ledPin, realLedState); // реализуем заданное состояние } else if (currentMillis < (OnTime + OffTime + summTime)){ realLedState = !ledState; digitalWrite(ledPin, realLedState); // реализуем новое состояние } else { ledState = LOW; summTime += OnTime + OffTime; } } else if (ledState == LOW) { if (currentMillis <= (OffTime + summTime)) { realLedState = ledState; digitalWrite(ledPin, realLedState); // реализуем заданное состояние } else if (currentMillis < (OnTime + OffTime + summTime)){ realLedState = !ledState; digitalWrite(ledPin, realLedState); // реализуем новое состояние } else { ledState = HIGH; summTime += OnTime + OffTime; } } } uint8_t getState(){ return realLedState; } }; Flasher led1(11, 300, 300, LOW); Flasher led2(12, 900, 900, HIGH); //Flasher led3(13, 300, 700, HIGH); void setup() { Serial.begin(9600); } void loop() { led1.Update(); led2.Update(); //led3.Update(); uint8_t val1 = led1.getState(); uint8_t val2 = led2.getState(); Serial.print(val1 + 2); Serial.print(" "); Serial.println(val2); } ==== К предыдущему коду добавлен класс кнопки ==== int ledPin7 = 7; class Flasher { // Переменные - члены класса // Инициализируются при запуске uint8_t ledPin; // номер пина со светодиодом uint16_t OnTime; // время включения в миллисекундах uint16_t OffTime; // время, когда светодиод выключен // Текущее состояние uint8_t ledState; // изначальное состояние светодиода uint8_t realLedState; // текущее состояние светодиода //uint32_t currentTime; // текущее время uint32_t summTime; // расчетное время свечения // Конструктор создает экземпляр Flasher и инициализирует // переменные-члены класса и состояние public: Flasher(uint8_t pin, uint16_t on, uint16_t off, uint8_t st) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = st; realLedState = st; //currentTime = 0; //currentPeriod = 0; summTime = 0; } void Update(){ uint32_t currentMillis = millis(); // текущее время в миллисекундах if(ledState == HIGH) { if (currentMillis <= (OnTime + summTime)) { realLedState = ledState; digitalWrite(ledPin, realLedState); // реализуем заданное состояние } else if (currentMillis < (OnTime + OffTime + summTime)){ realLedState = !ledState; digitalWrite(ledPin, realLedState); // реализуем новое состояние } else { ledState = LOW; summTime += OnTime + OffTime; } } else if (ledState == LOW) { if (currentMillis <= (OffTime + summTime)) { realLedState = ledState; digitalWrite(ledPin, realLedState); // реализуем заданное состояние } else if (currentMillis < (OnTime + OffTime + summTime)){ realLedState = !ledState; digitalWrite(ledPin, realLedState); // реализуем новое состояние } else { ledState = HIGH; summTime += OnTime + OffTime; } } } uint8_t getState(){ return realLedState; } }; class Cliker { // Переменные - члены класса // Инициализируются при запуске uint8_t bPin; // номер пина с кнопкой uint16_t counter; uint8_t b_state; uint32_t previousMillis; // последний момент смены состояния uint8_t pause ; uint8_t val; uint8_t debounceFlag; // Конструктор создает экземпляр Cliker и инициализирует // переменные-члены класса и состояние public: Cliker(int pin) { bPin = pin; pinMode(bPin, INPUT_PULLUP); debounceFlag = 0; counter = 0; b_state = 1; previousMillis = 0; pause = 10; } void Update() { if (!debounceFlag){ val = digitalRead(bPin); previousMillis = millis(); if (b_state != val){ debounceFlag = 1; } } else { uint32_t currentMillis = millis(); //if((b_state != digitalRead(bPin)) && (currentMillis - previousMillis >= pause)){ if(currentMillis - previousMillis >= pause){ counter ++; b_state = val; //Serial.println(counter); //previousMillis = currentMillis; debounceFlag = 0; } } } uint16_t getCounter(){ return counter; } }; Flasher led1(11, 300, 300, LOW); Flasher led2(12, 900, 900, HIGH); //Flasher led3(13, 300, 700, HIGH); Cliker but1(2); void setup() { pinMode(ledPin7, OUTPUT); Serial.begin(9600); } void loop() { but1.Update(); uint16_t ctr = but1.getCounter(); if (ctr % 2 == 1){ digitalWrite(ledPin7, 1); led1.Update(); } else { digitalWrite(ledPin7, 0); led2.Update(); } //led3.Update(); uint8_t val1 = led1.getState(); uint8_t val2 = led2.getState(); Serial.print(val1 + 2); Serial.print(" "); Serial.println(val2); } ==== Traffic lights example ==== /* * https://www.hackerspacetech.com/state-machine-with-arduino/ - State machine with Arduino * Traffic lights example * * Red light to pin 7 * Yellow light to pin 6 * Green light to pin 5 * * Pedestrian Red light to pin 4 * Pedestrian Green light to pin 3 * Pedestrian pushbutton pin 2 (it is connected to the GND, therefore internal PULLUP resistor must be ON) * * Arduino IDE 1.6.12 */ // Pins int red = 7, yellow = 6, green = 5; int p_red = 4, p_green = 3; int button = 2; // System variables byte state = 0; // initial state unsigned int i = 1; // system counter unsigned int del = 100; // system delay legnth boolean flag = false; void setup() { pinMode(red, OUTPUT); pinMode(yellow, OUTPUT); pinMode(green, OUTPUT); pinMode(p_red, OUTPUT); pinMode(p_green, OUTPUT); pinMode(button, INPUT_PULLUP); } void loop() { // Check button if(digitalRead(button) == 0) flag = true; switch(state){ case 0: digitalWrite(red, HIGH); digitalWrite(yellow, LOW); digitalWrite(green, LOW); if(flag){ digitalWrite(p_red, LOW); digitalWrite(p_green, HIGH); }else{ digitalWrite(p_red, HIGH); digitalWrite(p_green, LOW); } if((i%100)==0){ flag = false; state = 1; i = 0; } break; case 1: digitalWrite(red, HIGH); digitalWrite(yellow, HIGH); digitalWrite(green, LOW); digitalWrite(p_red, HIGH); digitalWrite(p_green, LOW); if((i%30)==0){ state = 2; i = 0; } break; case 2: digitalWrite(red, LOW); digitalWrite(yellow, LOW); digitalWrite(green, HIGH); digitalWrite(p_red, HIGH); digitalWrite(p_green, LOW); if((i%80)==0){ state = 3; i = 0; } break; case 3: digitalWrite(red, LOW); digitalWrite(yellow, HIGH); digitalWrite(green, LOW); digitalWrite(p_red, HIGH); digitalWrite(p_green, LOW); if((i%20)==0){ state = 0; i = 0; } break; default: break; } i++; delay(del); } ==== Traffic lights example (модернизированный код) ==== /* * https://www.hackerspacetech.com/state-machine-with-arduino/ - State machine with Arduino * Traffic lights example * * Red light to pin 7 * Yellow light to pin 6 * Green light to pin 5 * * Pedestrian Red light to pin 4 * Pedestrian Green light to pin 3 * Pedestrian pushbutton pin 2 (it is connected to the GND, therefore internal PULLUP resistor must be ON) * * Arduino IDE 1.6.12 */ // Pins int red = 7, yellow = 6, green = 5; int p_red = 4, p_green = 3; int button = 2; // System variables byte state = 0; // initial state unsigned int i = 1; // system counter unsigned int del = 100; // system delay legnth boolean flag = false; void change_traffic_lights(uint8_t r,uint8_t y, uint8_t g){ digitalWrite(red, r); digitalWrite(yellow, y); digitalWrite(green, g); } void change_pedestrian_lights(uint8_t r,uint8_t g){ digitalWrite(p_red, r); digitalWrite(p_green, g); } void setup() { pinMode(red, OUTPUT); pinMode(yellow, OUTPUT); pinMode(green, OUTPUT); pinMode(p_red, OUTPUT); pinMode(p_green, OUTPUT); pinMode(button, INPUT_PULLUP); } void loop() { // Check button if(digitalRead(button) == 0) flag = true; switch(state){ case 0: change_traffic_lights(1,0,0); if(flag){ change_pedestrian_lights(0,1); }else{ change_pedestrian_lights(1,0); } if((i%100)==0){ flag = false; state = 1; i = 0; } break; case 1: change_traffic_lights(1,1,0); change_pedestrian_lights(1,0); if((i%30)==0){ state = 2; i = 0; } break; case 2: change_traffic_lights(0,0,1); change_pedestrian_lights(1,0); if((i%80)==0){ state = 3; i = 0; } break; case 3: change_traffic_lights(0,1,0); change_pedestrian_lights(1,0); if((i%20)==0){ state = 0; i = 0; } break; default: break; } i++; delay(del); } /* * Traffic lights example * * Red light to pin 7 * Yellow light to pin 6 * Green light to pin 5 * * Pedestrian Red light to pin 4 * Pedestrian Green light to pin 3 * Pedestrian pushbutton pin 2 (it is connected to the GND, therefore internal PULLUP resistor must be ON) * * Arduino IDE 1.6.12 */ // Pins int red = 7, yellow = 6, green = 5; int p_red = 4, p_green = 3; int button = 2; // System variables byte state = 0; // initial state unsigned long i = 1; // system counter unsigned int del = 100; // system delay legnth boolean flag = false; void change_traffic_lights(uint8_t r,uint8_t y, uint8_t g){ digitalWrite(red, r); digitalWrite(yellow, y); digitalWrite(green, g); } void change_pedastrian_lights(uint8_t r,uint8_t g){ digitalWrite(p_red, r); digitalWrite(p_green, g); } void setup() { pinMode(red, OUTPUT); pinMode(yellow, OUTPUT); pinMode(green, OUTPUT); pinMode(p_red, OUTPUT); pinMode(p_green, OUTPUT); pinMode(button, INPUT_PULLUP); Serial.begin(9600); } void loop() { // Check button if(digitalRead(button) == 0) { flag = true; } delay(del); switch(state){ case 0: change_traffic_lights(0,0,1); change_pedastrian_lights(1,0); if(flag){ if((i%30)==0){ flag = false; Serial.print("case 0, state = 3 ");Serial.println(flag); state = 3; i = 1; } } break; case 1: change_traffic_lights(1,1,0); change_pedastrian_lights(1,0); if((i%30)==0){ Serial.print("case 1, state = 0 ");Serial.println(flag); state = 0; flag = false; i = 1; } break; case 2: change_traffic_lights(1,0,0); change_pedastrian_lights(0,1); if((i%100)==0){ Serial.print("case 2, state = 1 ");Serial.println(flag); state = 1; flag = false; i = 1; } break; case 3: change_traffic_lights(0,1,0); change_pedastrian_lights(1,0); if((i%20)==0){ Serial.print("case 3, state = 2 ");Serial.println(flag); state = 2; flag = false; i = 1; } break; default: break; } i++; } /* * Traffic lights example * * Red light to pin 7 * Yellow light to pin 6 * Green light to pin 5 * * Pedestrian Red light to pin 4 * Pedestrian Green light to pin 3 * Pedestrian pushbutton pin 2 (it is connected to the GND, therefore internal PULLUP resistor must be ON) * * Arduino IDE 1.6.12 */ // Pins int red = 7, yellow = 6, green = 5; int p_red = 4, p_green = 3; int button_1 = 2; int butState_1 = HIGH; int butDelay = 10; int checkButton_1 = 0; uint32_t prevButt_time_1 = 0; uint32_t prevTraffic_time = 0; // System variables byte state = 0; // initial state unsigned long i = 1; // system counter unsigned int del = 100; // system delay legnth boolean flag = false; void change_traffic_lights(uint8_t r,uint8_t y, uint8_t g){ digitalWrite(red, r); digitalWrite(yellow, y); digitalWrite(green, g); } void change_pedastrian_lights(uint8_t r,uint8_t g){ digitalWrite(p_red, r); digitalWrite(p_green, g); } uint8_t checkButton(){ uint8_t newButtonState = digitalRead(button_1); if(newButtonState != butState_1){ Serial.print("newButtonState = "); Serial.println(newButtonState); return true; } else { return false; } } void setup() { pinMode(red, OUTPUT); pinMode(yellow, OUTPUT); pinMode(green, OUTPUT); pinMode(p_red, OUTPUT); pinMode(p_green, OUTPUT); pinMode(button_1, INPUT_PULLUP); Serial.begin(9600); } void loop() { // Check button switch(state){ case 0: change_traffic_lights(0,0,1); change_pedastrian_lights(1,0); if(checkButton()){ prevTraffic_time = millis(); state = 5; Serial.println("state = 0; "); } break; case 5: change_traffic_lights(0,0,1); change_pedastrian_lights(1,0); if(millis() - prevTraffic_time >= 3000){ prevTraffic_time = millis(); state = 3; Serial.println("state = 5; "); } break; case 1: change_traffic_lights(1,1,0); change_pedastrian_lights(1,0); if(millis() - prevTraffic_time >= 3000){ prevTraffic_time = millis(); Serial.println("state = 1; "); state = 0; } break; case 2: change_traffic_lights(1,0,0); change_pedastrian_lights(0,1); if(millis() - prevTraffic_time >= 5000){ prevTraffic_time = millis(); Serial.println("state = 2; "); state = 1; } break; case 3: change_traffic_lights(0,1,0); change_pedastrian_lights(1,0); if(millis() - prevTraffic_time >= 2000){ prevTraffic_time = millis(); Serial.println("state = 3; "); state = 2; } break; default: break; } } ===== Передача информации от компьютера к Arduino ===== //sketch 6-01 int outPin = 13; void setup() { pinMode(outPin, OUTPUT); Serial.begin(9600); Serial.println("Enter 1 or 0"); } void loop() { if (Serial.available() > 0) { char ch = Serial.read(); Serial.print(ch); if (ch == '1') { digitalWrite(outPin, HIGH); } else if (ch == '0') { digitalWrite(outPin, LOW); } } } ===== Датчик температуры DS18B20 ===== // sketch_10_02_OneWire_DS18B20 #include #include const int busPin = 10; OneWire bus(busPin); DallasTemperature sensors(&bus); DeviceAddress sensor; void setup() { Serial.begin(9600); sensors.begin(); if (!sensors.getAddress(sensor, 0)) { Serial.println("NO DS18B20 FOUND!"); } } void loop() { sensors.requestTemperatures(); float tempC = sensors.getTempC(sensor); Serial.println(tempC); delay(1000); } ===== Термостат (с релейным регулятором) ===== #include #include #include // инициализируем объект-экран, передаём использованные // для подключения контакты на Arduino в порядке: // RS, E, DB4, DB5, DB6, DB7 LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const int tempPin = 10; // (1) const int heatPin = 9; const long period = 5000; // (2) OneWire oneWire(tempPin); // (3) DallasTemperature sensors(&oneWire); float setTemp = 0.0; // (4) long lastSampleTime = 0; void setup() { pinMode(heatPin, OUTPUT); Serial.begin(9600); Serial.println("t30 - sets the temperature to 30"); sensors.begin(); // (5) lcd.begin(16, 2); } void loop() { if (Serial.available()) { // (6) char command = Serial.read(); if (command == 't') { setTemp = Serial.parseInt(); Serial.print("Set Temp="); Serial.println(setTemp); } } long now = millis(); // (7) if (now > lastSampleTime + period) { lastSampleTime = now; float measuredTemp = readTemp(); // (8) float error = setTemp - measuredTemp; Serial.print(measuredTemp); Serial.print(", "); Serial.print(setTemp); lcd.setCursor(0, 0); lcd.print("realT setT "); lcd.setCursor(0, 1); lcd.print(measuredTemp,2); lcd.setCursor(8, 1); lcd.print(setTemp,2); if (error > 0) { // (9) digitalWrite(heatPin, HIGH); Serial.println(", 1"); } else { digitalWrite(heatPin, LOW); Serial.println(", 0"); } } } float readTemp() { // (10) sensors.requestTemperatures(); return sensors.getTempCByIndex(0); } * [[https://yadi.sk/d/2hHzcQzJYNExOg]] - библиотеки для проекта * [[https://youtu.be/dX9KMFFXTX4]] - КАК РАССЧИТАТЬ ТРАНЗИСТОРНЫЙ КЛЮЧ!!! {{::termostat.png?200|}} {{:termostat2.png?300|}} {{::imag2872_1.jpg?300|}} ===== DS18B20 (digital temperature sensor) and Arduino ===== https://create.arduino.cc/projecthub/TheGadgetBoy/ds18b20-digital-temperature-sensor-and-arduino-9cc806 ===== Подключение дисплея ===== * [[http://amperka.ru/product/text-lcd-16x2?utm_source=man&utm_campaign=tft&utm_medium=wiki|Текстовый экран 16×2]] * [[http://wiki.amperka.ru/%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D1%8B:text-lcd-16x2|Текстовый экран 16×2 (Подключение и настройка)]] ==== Конечный автомат на примере PICOBOT ==== * [[https://www.cs.hmc.edu/csforall/Introduction/Introduction.html]] - теория * [[https://www.cs.hmc.edu/picobot/]] * [[https://www.cs.hmc.edu/~dodds/picobot/]] * [[https://www.cs.hmc.edu/~dodds/IST338/SLIDES/Lec11_15_ist338.pdf]] ==== ООП Азбука Морзе ==== * [[http://www.mathertel.de/Arduino/FiniteStateMachine.aspx]] ===== Saimon Monk ===== * [[http://simonmonk.org/]] * [[https://www.ozon.ru/person/135482341/]] * [[https://dic.academic.ru/book.nsf/65983302/%D0%9F%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D1%83%D0%B5%D0%BC%20Arduino.%20%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B%20%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B%20%D1%81%D0%BE%20%D1%81%D0%BA%D0%B5%D1%82%D1%87%D0%B0%D0%BC%D0%B8]] * [[https://github.com/simonmonk/programming_arduino/tree/master/sketch_05_01]] - массивы * [[https://github.com/simonmonk/programming_arduino/tree/master/sketch_05_04]] - строки * [[https://github.com/simonmonk/programming_arduino/tree/master/sketch_05_05]] - Morse Code * [[https://github.com/simonmonk/programming_arduino/tree/master/sketch_06_01]] - Передача информации по последовательному порту от компьютера к Arduino * [[https://github.com/simonmonk/nextsteps2/blob/master/sketch_12_01_PC_to_Arduino/sketch_12_01_PC_to_Arduino.ino]] - Передача информации по последовательному порту от компьютера к Arduino 2 * [[https://github.com/simonmonk/nextsteps2/blob/master/sketch_12_02_Arduino_Sender/sketch_12_02_Arduino_Sender.ino]] - Обмен между несколькими Arduino - Sender * [[https://github.com/simonmonk/nextsteps2/blob/master/sketch_12_03_Arduino_Receiver/sketch_12_03_Arduino_Receiver.ino]] - Обмен между несколькими Arduino - Receiver * [[https://github.com/simonmonk/make_action/blob/master/arduino/experiments/mixing_colors/mixing_colors.ino]] - RGB светодиод * [[https://github.com/simonmonk/nextsteps2/blob/master/sketch_10_02_OneWire_DS18B20/sketch_10_02_OneWire_DS18B20.ino]] - DS18B20 1 * [[https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf]] - PDF документация на DS18b20 * [[http://mypractic.ru/ds18b20-datchik-temperatury-s-interfejsom-1-wire-opisanie-na-russkom-yazyke.html]] * [[https://create.arduino.cc/projecthub/TheGadgetBoy/ds18b20-digital-temperature-sensor-and-arduino-9cc806]] * [[https://github.com/simonmonk/nextsteps2/blob/master/sketch_10_03_OneWire_DS18B20_2/sketch_10_03_OneWire_DS18B20_2.ino]] - DS18B20 2 * [[https://github.com/simonmonk/make_action/blob/master/arduino/experiments/simple_thermostat/simple_thermostat.ino]] - простой термостат * [[https://github.com/simonmonk/make_action/blob/master/arduino/experiments/pid_thermostat/pid_thermostat.ino]] - термостат с PID регулятором * [[https://playground.arduino.cc/Code/PIDLibrary]] - Arduino PID Library by Brett Beauregard * [[https://github.com/br3ttb/Arduino-PID-Library/]] * [[https://github.com/simonmonk/nextsteps2/blob/master/sketch_04_01_interrupt/sketch_04_01_interrupt.ino]] - прерывания 1 * [[https://github.com/simonmonk/nextsteps2/blob/master/sketch_04_02_interrupt_flash/sketch_04_02_interrupt_flash.ino]] - прерывания 2 * ===== Датчики ===== * [[http://we.easyelectronics.ru/Theory/datchiki-i-acp-dlya-chaynikov-praktikov-1-3-vvedenie.html ]] ===== ПИД регуляторы ===== * [[http://we.easyelectronics.ru/Theory/pid-regulyatory--dlya-chaynikov-praktikov.html]] * [[http://kpolyakov.spb.ru/uni/teapot.htm]] * [[http://www.239.ru/userfiles/file/Robobook99-99-99-20short.pdf]] * [[http://robofob.ru/materials/articles/pages/Karpov_mobline1.pdf]] - "ПИД-управление в нестрогом изложении". Карпов В.Э. ===== AlphaBot ===== * [[https://www.waveshare.com/wiki/AlphaBot]] * [[http://robocraft.ru/blog/arduino/170.html]] - Практическое программирование Arduino/CraftDuino - драйвер двигателей L293D * [[http://edurobots.ru/2014/04/arduino-servoprivod/]] - Управление сервоприводом * [[https://www.allnet.de/fileadmin/transfer/products/111901.pdf]] - DYP serial Ultrasonic Sensor ===== Протокол передачи данных I2C ===== * http://easyelectronics.ru/interface-bus-iic-i2c.html * http://robocraft.ru/blog/communication/780.html ==== Finite State Machine ==== * [[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D1%8B%D0%B9_%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82| Конечный автомат (WIKI)]] * [[https://www.hackerspacetech.com/state-machine-with-arduino/]] - **State machine with Arduino** (Светофор) * [[https://автошколадома.рф/tema-61-signaly-svetofora/]] - сигналы светофора * [[https://devhub.io/repos/yoreek-Arduino-StateMachine]] - Светофор + ООП * [[http://playground.arduino.cc/Code/FiniteStateMachine]] * [[http://microsin.net/programming/avr/arduino-onebutton-library.html]] - Arduino OneButton Library * ==== Справочные ресурсы по программированию на Arduino ==== * https://www.arduino.cc/reference/en/ * https://www.arduino.cc/reference/en/language/functions/communication/serial/ * https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/ * http://arduino.ru/Reference * [[http://robocraft.ru/blog/arduino/76.html]] - программирование работы с COM-портом * [[http://playground.arduino.cc/Interfacing/Python]] - Arduino and Python ===== Полезные учебные ресурсы ===== * [[https://www.sololearn.com/Course/CPlusPlus/]] - C++ Tutorial (Web версия на английском) * [[https://play.google.com/store/apps/details?id=com.sololearn]] - Под android - SoloLearn: Учимся программировать (на русском) * [[https://stepik.org/course/363]] Введение в программирование (C++) * [[https://www.coursera.org/learn/roboty-arduino]] - Строим роботов и другие устройства на Arduino. От светофора до 3D-принтера * [[https://yadi.sk/i/5CMqjaQX3Qr3Ns | Справочник по языку программирования для Arduino (*.pdf)]] * [[https://yadi.sk/i/B4dNTU4g3Qr3hQ | Arduino - быстрый старт (учебное пособие *.pdf)]] * [[https://youtu.be/4Ue2BuqXlMA]] - 16 лучших Arduino проектов AlexGyver * [[http://robocraft.ru/files/books/arduino_notebook_rus_v1-1.pdf]] * [[https://habr.com/post/357908/]] * [[https://pikabu.ru/story/2000_idey_i_urokov_arduino_4289823]] * [[http://edurobots.ru/kurs-arduino-dlya-nachinayushhix/]] * [[http://digitrode.ru/computing-devices/mcu_cpu/522-ampermetr-na-arduino-svoimi-rukami.html]] - амперметр ===== Литература ===== * [[http://publ.lib.ru/ARCHIVES/V/VOYCEHOVSKIY_Yanush/_Voycehovskiy_Ya..html]] - Войцеховский Я. Радиоэлектронные игрушки (электроника дома, на работе, в школе). (Nowoczesne zabawki: Elektronika w domu, pracy, szwkole, 1974) * [[http://portal.tpu.ru/SHARED/l/LENAOLYA/job/imoyak/Tab/electronics.pdf]] А. В. Лукутин, Е. Б. Шандарова. ЭЛЕМЕНТЫ ЭЛЕКТРОНИКИ. Учебное пособие по курсу «Электротехника, электроника» * [[http://publ.lib.ru/ARCHIVES/S/SVOREN'_Rudol'f_Anatol'evich/_Svoren'_R.A..html#001]] - Рудольф Анатольевич Сворень ===== Нейронная сеть на Arduino ===== * [[http://a-bolshakov.ru/index/0-396]] ===== Преподавание курса «Изучение киберфизических устройств и систем на базе микропроцессорных плат Arduino» ===== * [[http://dpo.temocenter.ru/dlya-pedagogov/course/54.html]] https://ru.hexlet.io/courses/cli-basics/lessons/users-and-groups/theory_unit https://ru.hexlet.io/courses/cli-basics/lessons/sudo/theory_unit