Radar

Muszę przyznać, że o zrobieniu takiego projektu myślałem już od dawna, ale zawsze wydawało mi się to nieosiągalne. Ale udało się zbudowałem prosty radar, pokazujący na ekranie komputera położenie przeszkód. Udało się to głownie dzięki temu, że zmieniłem trochę zdanie odnośnie wysokopoziomowych języków, takich jak na przykład java.  Teraz gdy nie muszę się już męczyć z ciągle nie działającymi komunikacjami, podejrzanymi bibliotekami, wykonanie takiego projektu okazało się proste. A o to efekt, widok przeszkód na ekranie komputera.

 

Co do elektroniki, to nie ma co się rozpisywać, bo jest niezwykle prosta, wykorzystałem tą samą płytką z atmega8 co w poprzednim artykule „Własne Arduino”. Do płytki dołączyłem serwo i dalmierz firmy Sharp 2D120x. Ponieważ serwo pobiera mało energii bez obaw mogłem podłączyć je do zasilania z USB. Zrobiłem tak, ponieważ mam już doświadczenie z tymi serwami, znam ich pobór prądu przy różnych obciążeniach. Jednak polecam za każdym razem sprawdzić, czy serwo nie pobiera znacznych prądów, w przeciwnym przypadku można sobie uszkodzić port USB. Poniżej przedstawiam zdjęcie stanowiska z dalmierzem i elektroniki.

Zadaniem programu w kontrolerze jest dokonanie pomiaru napięcia na zerowym wejściu analogowym (PORTC.0), przeliczeniu zmierzonej wartości na centymetry i wysłanie Wyniku do komputera. Poniżej przedstawiam program.

#include <Servo.h>

Servo myservo; // create servo object to control a servo 
                // a maximum of eight servo objects can be created 

int pos = 0; // variable to store the servo position 

void setup()
{ 
  myservo.attach(9); // attaches the servo on pin 9 to the servo object 
  Serial.begin(19200);
} 

void loop()
{ 
  for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos); // tell servo to go to position in variable 'pos'
    delay(20); // waits 15ms for the servo to reach the position
    int analogValue = analogRead(0);
    float dis = 2901/(analogValue + 1);
    Serial.print(char(pos));
    Serial.print(char(dis));
  }
  for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees 
  {                                
    myservo.write(pos); // tell servo to go to position in variable 'pos' 
    delay(20); // waits 15ms for the servo to reach the position
    int analogValue = analogRead(0);
    float dis = 2901/(analogValue + 1);
    Serial.print(char(pos));
    Serial.print(char(dis));
  } 
}

Program jest bardzo prosty, przemiata serwem na boki robiąc pomiary, po każdym przesunięciu serwa o 1 stopień. Jedyną ciekawą linijką jest:

float dis = 2901/(analogValue + 1);

gdzie dochodzi do zamiany wartości odczytanej z czujnika na centymetry, została zastosowana tutaj metoda aproksymacji danych z czujnika do funkcji typu dys = a/(analogValie + b), a i b to parametry wyliczone na podstawie danych. Szczegóły opiszę w osobnym artykule.

Program na komputerze powstał w bardzo ciekawym środowisku Processing. Stosuje się w nim język Java, ale dostarczone biblioteki mocno uproszczają całą pracą na przykład obsługa portu USB jest dziecinnie łatwa, a  wyrysowanie na ekranie punktów nie stanowi większego problemu. Po prostu środowisko jest stworzone do wykonywania właśnie takich programów. Poniżej przedstawiam mój kod programu.

import processing.serial.*;

Serial myPort;
float x,y;
int val,pos, _pos;
punkt mapa[] = new punkt[181];

void setup() 
{
  size(600, 300);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 19200);
  println(portName);
  stroke(0,255,0);
  background(0);

  for(int i = 0; i < mapa.length; i++)
    mapa[i] = new punkt();
}
void draw()
{
  translate(width/2, 300);
  rotate(PI);
  if ( myPort.available() &rt; 0) 
  {
     _pos = pos;
     pos = myPort.read();
     print("pos = ");
     print(pos);
     val = myPort.read();
     print(" val = ");
     println(val);
  }
}

  if(pos < 180 && pos &rt; 0)
  {
    mapa[pos].val = val;
    if(pos < _pos)
      mapa[pos-1].val = 35;
    else
      mapa[pos+1].val = 35;
    float _pos = radians(pos);
    mapa[pos].x = -cos(_pos)*val;
    mapa[pos].y = sin(_pos)*val;
    mapa[pos].f = false;
  }
  for(int i = 0; i < 180; i++)
  {
    if(mapa[i].val < 30)
    {
      if(i < 180 && i &rt; 0)
      {
        if(abs(mapa[i-1].val - mapa[i].val) <= 0)
          mapa[i].f = true;
        else
          mapa[i].f = false;

        if(abs(mapa[i+1].val - mapa[i].val) <= 0)
          mapa[i].f = true;
        else
          mapa[i].f = false;
      }
    }
  }
  background(0); 
  noFill();
  stroke(0,255,0); 
  ellipse(0, 0, 600, 600);
  ellipse(0, 0, 500, 500);
  ellipse(0, 0, 400, 400);
  ellipse(0, 0, 300, 300);
  ellipse(0, 0, 250, 250);
  ellipse(0, 0, 200, 200);
  ellipse(0, 0, 150, 150);
  ellipse(0, 0, 100, 100);
  ellipse(0, 0, 50, 50); 
  fill(200,60,60);
  noStroke();

  for(int i = 1; i < 180; i++)
  {
    if(mapa[i].f == true)
    {
      ellipse(mapa[i].x*10, mapa[i].y*10, 10, 10);
    }
  }
}

class punkt
{
  int val;
  float x,y;
  boolean f;
}

Nie będę tego programu szczegółowo opisywał, generalnie to działa tak, że pobiera dane z portu przelicza położenie kropki na współrzędne dla ekranu no i rysuje kropkę. Po drodze dodatkowo odfiltrowuje dane poza zakresu czujnika (30cm) i wyrzucam szumy w formie pojedynczych punktów. W efekcie otrzymujemy mniej więcej obraz tego co widzi czujnik.

Po niżej przedstawiam film prezentujący całość podczas działania.

Facebook Comments

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.