LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

[PROJEKT] Romi Chassis – sterowanie za pomocą smartfona

W pierwszym programie można było sterować kierunkiem ruchu podwozia Romi Chassis za pomocą 4 przycisków. Natomiast w drugim kontrolowana jest prędkość poruszania się. Aby to zrealizować, przyciski zastąpiono dwoma sliderami. Jeden z nich będzie odpowiadał za jazdę do przodu i do tyłu, drugi natomiast do obrotu w prawo oraz w lewo.

Aby nie tracić układu potrzebnego do pierwszego programu, można zapisać go w pamięci telefonu. Aby to zrobić należy w menu wybrać pozycje interface a następnie export. Teraz należy wpisać nazwę naszego interfejsu np. Program_1.

Pierwszym krokiem jest dodanie sliderów – pionowy będzie odpowiadał za jazdę do przodu i do tyłu, poziomy będzie służył do obrotu – w prawo lub lewo. Dodaje się je podobnie jak przyciski w pierwszym programie.

Slidery można ułożyć w następujący sposób:

Rysunek 8. Slidery w interfejsie dla drugiego programu

Teraz należy ustawić odpowiednie parametry. Najpierw zajmiemy się górnym sliderem. Aby wejść w jego ustawienia, klikamy na niego. Wybieramy nasz slider i opcję set id. W tym miejscu wpisujemy ID slidera. Teraz musimy wybrać następujące parametry: set min,max. Wartości te będą wartościami maksymalnymi dla poruszania się do przodu oraz tyłu. Ustawiamy wartość minimum na -100, a maksimum na 100. Następnie należy zaznaczyć opcje send when moved (wysyłaj za każdym razem gdy suwak na sliderze zostanie przesunięty) oraz auto return (powrót do pozycji zerowej), don’t send space (nie wysyłaj spacji po ID). Przesuwając suwak do góry zostanie wysłana komenda np. F56 a w dół F-65.

Dla drugiego slidera trzeba postąpić analogiczne jak dla pierwszego, z tą różnica, że należy przypisać mu inne ID, np. literę S (od skręt).

Proces tworzenia aplikacji został ukazany na poniższym wideo.

W tym momencie można przejść do kodu dla programu drugiego:

// Romi Chassis – Romi Chassis - Sterowanie przy pomocy smartfona
// Program 2
// Autor: Patryk Mądry 
// Mikrokontroler 2017 r.


char OdebraneDane[20]; 
byte indeks;
char znak ="";

int predkosc = 0;

void Jedz_do_przodu(int i)
{
  // Lewy silnik
  digitalWrite(6,LOW);
  analogWrite(10,i);

  // Prawy silnik 
  digitalWrite(7,LOW);
  analogWrite(11,i);
}

void Jedz_do_tylu(int i)
{
  // Lewy silnik
  digitalWrite(6,HIGH);
  analogWrite(10,i);
  
  // Prawy silnik 
  digitalWrite(7,HIGH);
  analogWrite(11,i);
}

void Obrot_w_prawo(int i)
{
  // Lewy silnik
  digitalWrite(6,LOW);
  analogWrite(10,i);
  
  // Prawy silnik 
  digitalWrite(7,HIGH);
  analogWrite(11,i);
}

void Obrot_w_lewo(int i)
{
  // Lewy silnik
  digitalWrite(6,HIGH);
  analogWrite(10,i);
  
  // Prawy silnik 
  digitalWrite(7,LOW);
  analogWrite(11,i);
}

void Stop()
{
  // Lewy silnik
  digitalWrite(6,LOW);
  analogWrite(10,0);
  
  // Prawy silnik 
  digitalWrite(7,LOW);
  analogWrite(11,0);
}


void setup() {

  Serial.begin(38400); // Predkosc dla modułu Bluetooth
  
  // Ustawienie pinów do obsługi sterownika silników 
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);

  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
}

void loop()
{
  if (Serial.available() > 0 ) // Sprawdzanie czy zostały odebrane dane
  {
    delay(20);

    // Zapisanie odebranych danych do tablicy znaków OdebraneDane[]
    do
    {
      znak = (char)Serial.read();
      OdebraneDane[indeks] = znak;
      indeks++;
    }while(znak != '\n');

    //Zerowanie zmiennych
    OdebraneDane[indeks] = 0;
    indeks=0;

    if (OdebraneDane[0]=='F') //Sprawdzanie pierwszego znaku, jeżeli F jedz do przodu/tyłu 
    {
      predkosc= atoi(OdebraneDane+1); // konwersja znaków z tablicy OdebraneDane[] na wartosc liczbową 

      if ( predkosc > 5) // Jeżeli otrzymana wartosc liczbowa jest większa niż 5 jedz do przodu 
      {
            Jedz_do_przodu(predkosc);
      }
      else if  ( predkosc < -5) // Jeżeli otrzymana wartosc liczbowa jest większa niż 5 jedz do tylu
      {
        Jedz_do_tylu(abs(predkosc)); // wartosc bezwglednia zmiennej predkosc 
      }
      else 
      {
         Stop();
      }
    }
    else if (OdebraneDane[0]=='R') //Sprawdzanie pierwszego znaku, jeżeli R - obrot w prawo lub lewo 
    {
      predkosc= atoi(OdebraneDane+1); // konwersja znaków z tablicy OdebraneDane[] na wartosc liczbową 

      if ( predkosc > 5) // Jeżeli otrzymana wartosc liczbowa jest większa niż 5 - obrot w prawo
      {
        Obrot_w_prawo(predkosc);
      }
      else if  ( predkosc < -5) // Jeżeli otrzymana wartosc liczbowa jest większa niż -5 - obrot w lewo
      {
        Obrot_w_lewo(abs(predkosc)); // wartosc bezwglednia zmiennej predkosc 
      }
      else 
      {
        Stop();
      }
    }
  }
}

Na początku dodano zmienną prędkość. Będzie w niej przechowywana prędkość odebrana za pośrednictwem modułu Bluetooth.

char OdebraneDane[20]; 
byte indeks;
char znak ="";

int predkosc = 0;

Funkcje oraz ustawienia pozostają bez zmian. Jednakże zmianie uległa zawartość pętli głównej programu:

void loop()
{
  if (Serial.available() > 0  ) // Sprawdzanie czy zostały odebrane dane
  {
    delay(20);

    // Zapisanie odebranych danych do tablicy znaków OdebraneDane[]
    do
    {
      znak = (char)Serial.read();
      OdebraneDane[indeks] = znak;
      indeks++;
    }while(znak != '\n');

    //Zerowanie zmiennych
    OdebraneDane[indeks] = 0;
    indeks=0;

    if (OdebraneDane[0]=='F') //Sprawdzanie pierwszego znaku, jeżeli F jedz do przodu/tyłu 
    {
      predkosc= atoi(OdebraneDane+1); // konwersja znaków z tablicy OdebraneDane[] na wartosc liczbową 
          
      if ( predkosc > 5) // Jeżeli otrzymana wartosc liczbowa jest większa niż 5, jedz do przodu 
      {
        Jedz_do_przodu(predkosc);
      }
      else if  ( predkosc < -5) // Jeżeli otrzymana wartosc liczbowa jest większa niż 5 jedz do tylu
      {
        Jedz_do_tylu(abs(predkosc)); // wartosc bezwglednia zmiennej predkosc 
      }
      else 
      {
        Stop();
      }
    }
    else if (OdebraneDane[0]=='R') //Sprawdzanie pierwszego znaku, jeżeli R - obrot w prawo lub lewo 
    {
      predkosc= atoi(OdebraneDane+1); // konwersja znaków z tablicy OdebraneDane[] na wartosc liczbową 
          
      if ( predkosc > 5) // Jeżeli otrzymana wartosc liczbowa jest większa niż 5 - obrot w prawo
      {
        Obrot_w_prawo(predkosc);
      }
      else if  ( predkosc < -5) // Jeżeli otrzymana wartosc liczbowa jest większa niż -5 - obrot w lewo
      {
        Obrot_w_lewo(abs(predkosc)); // wartosc bezwglednia zmiennej predkosc 
      }
      else 
      {
        Stop();
      }
    }
  }
}

Najpierw program sprawdza czy zostały odebrane jakieś dane. Jeżeli tak, zostają one zapisane do tablicy OdebraneDane[].

Następnie sprawdzany jest pierwszy znak jaki został odebrany. Jeżeli jest to litera F znaczy to że swoją pozycje zmienił slider odpowiedzialny za jazdę do przodu/tyłu. Należy dokonać konwersji znaków z tablicy na typ liczbowy (int). Odbywa się to za pomocą funkcji atoi(), której argumentem są znaki z tablicy (pomijając pierwszy znak czyli F). Wartość ta zapisywana jest w zmiennej predkość. Następnie program sprawdza jej wartość. Jeżeli jest ona większa niż 5 podwozie ma się poruszać do przodu. Natomiast gdy jej wartość jest mniejsza niż – 5, podwozie powinno poruszać się do tyłu.

Wartość zmiennej prędkość jest przesyłana do odpowiedniej funkcji odpowiedzialnej za ruch np. Jedz_do_przodu().

Należy jednak pamiętać, że funkcje do poruszania przyjmują tylko wartości z przedziału 0…255, podanie innych wartości może spowodować nieoczekiwane konsekwencje (np. duże prędkości silników). Dlatego w przypadku, gdy w otrzymanych danych znajduje się liczba ujemna, należy zastosować funkcję abs(), aby otrzymać wartość dodatnią, która może być użyta w funkcjach do poruszania się (jedz_do_przodu, obrot_w_prawo itd.).

Działanie programu drugiego zostało pokazane na poniższym wideo:

 

Autor: Patryk Mądry