Инструменты пользователя

Инструменты сайта


kiber_tc_2018

Содержание

Изучение киберфизических устройств

Основы электроники

Электроизмерительные приборы на Arduino

Практические задания

Схемотехника

Arduino Nano 3.0 распиновка

Двухканальный модуль управления двигателем HG7881 HG7881CP

Простой код для управления реверсивным движением двигателей с равномерным ускорением и замедлением (двухканальный драйвер двигателя 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

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); 
}

Управление питанием посредством кнопки

Режимы энергосбережения (Sleep Modes)

Ключевые ресурсы

Характеристика двигателя постоянного тока Makeblock 81340 180 Optical Encoder Motor

Программирование мобильного робота

Шасси Makeblock, двигатель «Makeblock 81340 180 Optical Encoder Motor», драйвер 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);
}

Вариант 2.1. Простейший релейный регулятор движения по линии + ультразвуковой датчик препятствия (промежуточный вариант, требует доработки)

 
#include <Ping.h>
 
 
#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 <Ping.h>
 
/*
 
*/
#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;
   }
}

Ультразвуковой датчик

Bluetooth модуль HC-06

Указатели в C для Ардуино

Принципы программирования оптических энкодеров

Прерывания по таймеру

О прерываниях

Дополнительные материалы по управлению двигателями...

АЦП

АЦП

Простейший аналоговый пробник

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 <OneWire.h>
#include <DallasTemperature.h>
 
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 <OneWire.h>
#include <DallasTemperature.h>
 
#include <LiquidCrystal.h>
// инициализируем объект-экран, передаём использованные 
// для подключения контакты на 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);  
}

DS18B20 (digital temperature sensor) and Arduino

Подключение дисплея

Конечный автомат на примере PICOBOT

ООП Азбука Морзе

Saimon Monk

Датчики

ПИД регуляторы

AlphaBot

Протокол передачи данных I2C

Finite State Machine

Справочные ресурсы по программированию на Arduino

Полезные учебные ресурсы

Литература

Нейронная сеть на Arduino

Преподавание курса «Изучение киберфизических устройств и систем на базе микропроцессорных плат Arduino»

kiber_tc_2018.txt · Последние изменения: 2019/05/06 14:49 — Sergey Kondrashov