Локатор - эксперименты с Arduino и Processing

Для самообучения сделал сканирующий ультразвуковой локатор (УЗ модуль на серве), который отсылает данные по Bluetooth (как в последовательный порт), и эти данные отрисовывает программа на Processing. В результате получается 100-градусный сектор в котором вспыхивают и медленно гаснут очертания предметов, эхо от которых улавливает радар.

Я пытался ловить несколько эх на один импульс, чтобы рисовать препятствия которые одновременно попали в луч, но находящиеся на разном расстоянии. Но локатор, скорее, рисует переотражения пришедшие со сторон 😉

Схему уже разобрал так что фоток нету 😇

Код для загрузки в Arduino:

#include <LiquidCrystal.h>
#include <stdarg.h>
#include <Servo.h>
// LCD connector;
// 1   2   3   4   5   6   7   8   9
// GND U+  A0  E   D4  D5  D6  D7  UBL+
// GND 5V  D7  D8  D9  D10 D11 D12
// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

const int minAngle = -50;
const int maxAngle = +50;
const int angleStep = 4;
const int MAX_IN_BEAM = 5;

void lcdPrint(char *fmt, ... ){
  char tmp[16]; // resulting string limited to 16 chars
  va_list args;
  va_start (args, fmt);
  vsnprintf(tmp, 128, fmt, args);
  va_end (args);
  lcd.print(tmp);
}

void serPrint(char *fmt, ... ){
  char tmp[16]; // resulting string limited to 16 chars
  va_list args;
  va_start (args, fmt);
  vsnprintf(tmp, 128, fmt, args);
  va_end (args);
  Serial.print(tmp);
}

// variables to take x number of readings and then average them
// to remove the jitter/noise from the DYP-ME007 sonar readings
const int numReadings = 2;

// setup pins and variables for DYP-ME007 sonar device
int echoPin = 2; // DYP-ME007 echo pin (digital 2)
int initPin = 3; // DYP-ME007 trigger pin (digital 3)

unsigned long lastDistance = 0; // variable for storing the distance (cm)

Servo myservo;  // create servo object to control a servo
const int servoPin = 6;

int servo = 0;
int servoDir = 1;

void setup() {
  pinMode(4, OUTPUT);  // LCD V;
  pinMode(initPin, OUTPUT); // set init pin 3 as output
  pinMode(echoPin, INPUT); // set echo pin 2 as input

  myservo.attach(servoPin);  // attaches the servo on pin 6 to the servo object

  digitalWrite(4, HIGH); // power the LCD;

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  tone(5,500);

  // Print a message to the LCD.
  lcd.print("SoundLocator 1.0");
  delay(1000);
  lcd.clear();

  noTone(5);

  Serial.begin(115200);

//  pinMode(servoPin, OUTPUT);
  myservo.write(0);              // tell servo to go to position in variable 'pos'
}

void loop() {
  unsigned long pulseTime;
  float distance[MAX_IN_BEAM];
  unsigned long maxWaitTime = 50000UL;

  int found=0;
  for (int i=0; i<MAX_IN_BEAM; i++) {
    if (i==0) {
     digitalWrite(initPin, HIGH); // send 10 microsecond pulse
     delayMicroseconds(10); // wait 10 microseconds before turning off
     digitalWrite(initPin, LOW); // stop sending the pulse
    } else {
     digitalWrite(initPin, HIGH); // cheat locator module to force it listen without sending pulse
     digitalWrite(initPin, LOW); // stop sending the pulse
    }

    pulseTime = pulseIn(echoPin, HIGH, maxWaitTime); // Look for a return pulse, it should be high as the pulse goes low-high-low
    if (pulseTime > 0) {
      distance[found] = float(pulseTime)/58.0 + (found>0 ? distance[found-1] : 0);
      found++;
    }

    maxWaitTime-= pulseTime;
    if (maxWaitTime <= 0)
      break;
  }

  serPrint("L%d", servo);
  for (int i=0; i<found; i++) {
    serPrint(",%d", int(round(distance[i])));
  }
  serPrint("\r\n");

  myservo.write(90-servo);              // tell servo to go to position in variable 'pos'
  servo+= servoDir;
  if (servo >= maxAngle) {
    servoDir = -angleStep;
  } else
  if (servo <= minAngle) {
    servoDir = +angleStep;
  }

  lcd.setCursor(0, 0);
  lcdPrint("L:%-1d", found);
  lcd.setCursor(6, 1);
  lcdPrint("S=%-5d", servo);
  lcd.setCursor(12, 1);
  lcdPrint("D=%-2d", servoDir);

  lcd.setCursor(12, 0);
  lcdPrint("1=%-5d", found ? 0 : distance[0]);
  delay(100);
}

Код в Processing:

import processing.serial.*; // serial library

PFont font;

boolean init_com = false;
Serial g_serial = null;

static int minAngle = -50;
static int maxAngle = +50;
static int angleStep = 4;
static int MAX_IN_BEAM = 5;
static int START_INTENSITY = 200;

static class Point {
  int distance;
  int intensity;

  Point() {
    distance = 0;
    intensity = 0;
  }

  void fade() {
    if (intensity > 0) {
      intensity--;
      if (intensity == 0)
         distance = 0;
    }
  }

  void setDistance(int aDistance) {
    distance = aDistance;
    intensity = START_INTENSITY;
  }
}

static class Scan {
  Point points[];

  Scan (int num) {
    points = new Point[num];
    for (int i=0; i<num; i++)
      points[i] = new Point();
  }
}

static int NUM_SCANS = (maxAngle-minAngle)/angleStep+1;
static Scan scans[] = new Scan[NUM_SCANS];
static {
  for (int i=0; i<NUM_SCANS; i++)
    scans[i] = new Scan(MAX_IN_BEAM);
}

int lastAngle = 0;

void setup() {
  size(1024, 768, P3D);
  font = createFont("Arial",18);
  textFont(font);
  g_serial = new Serial(this, "COM19", 115200);
  init_com = true;
}

void fadeAll() {
  for (int a=minAngle; a<=maxAngle; a+=angleStep) {
     int scanNum = (a-minAngle)/angleStep;
     Scan scan = scans[scanNum];
     for (int l=0; l<scan.points.length; l++) {
       scan.points[l].fade();
     }
  }
}

int R = 500;
int rArr = 50;
int locAng = 15;

void draw() {
  if (init_com) {
//    if  (g_serial.available() >100) g_serial.clear();
    while (g_serial.available() >= 1)
      processSerialData();
  }

  background(25,10,10);
  noLights();
 // perspective();
  noStroke();
  colorMode(HSB, 100);
  pushMatrix();
  translate(width/2, height-rArr, 0);
  noFill();
  ellipseMode(CENTER);

  float ab1 = radians(minAngle-90);
  float ab2 = radians(maxAngle-90);
  for (int d = 20; d<=R; d+=20) {
    noFill();
    stroke(float(d)/R*100, 50, 45);
    arc(0,0,d*2,d*2,ab1,ab2);
    fill(float(d)/R*100, 100, 100);
    textAlign(RIGHT, CENTER);
    text(d, round(d*cos(ab1))-5, round(d*sin(ab1)));
    textAlign(LEFT, CENTER);
    text(d, round(d*cos(ab2))+5, round(d*sin(ab1)));
  }

  noFill();
  lights();
  int prevX = 0;
  int prevY = 0;
  boolean first = true;
  strokeWeight(4);

  for (int a = minAngle; a <= maxAngle; a+= angleStep) {
    int scanNum = (a-minAngle)/angleStep;
    Scan scan = scans[scanNum];

    for (int l=0; l<scan.points.length; l++) {
      Point point = scan.points[l];
      if (point.intensity == 0)
        continue;

      int d = min(R, point.distance);
      float a1 = radians(a-90);
      float a2 = radians(a-90+angleStep);
      int x1 = round(d*cos(a1));
      int y1 = round(d*sin(a1));
      int x2 = round(d*cos(a2));
      int y2 = round(d*sin(a2));
      d = round(float(d)/R*100.0);
      stroke(d, 100, point.intensity/(START_INTENSITY/100));
      line(x1, y1, x2, y2);
//      stroke(d, 50, point.intensity/(START_INTENSITY/100));
//      arc(0,0,d*2,d*2, a1, a2);
//      println("a="+a+", d"+l+"="+d);
    }
  }

  strokeWeight(1);
  popMatrix();
  stroke(0, 50, 50);
  translate(width/2, height-rArr, 0);
  rotateX(-PI/6);
  rotateY(-radians(lastAngle));
  fill(0,50,50);

  pushMatrix();
  pushMatrix();
  box(50,15,5);
  popMatrix();
  translate(0, 0, 0);
  rotateZ(PI/2);
  rotateX(-PI/2);
  rotateY(PI/2);

  int dx = round(sin(radians(locAng/2))*rArr/2);
  triangle(-dx, rArr, +dx, rArr, 0, 7);
  popMatrix();

  fadeAll();
}

void processSerialData() {
  boolean found = false;
  while (g_serial.available() > 0) {
    if (g_serial.read() == 'L') {
      found = true;
      break;
    }
  }
  if (!found)
    return;

  String sIn = g_serial.readString();
  if (sIn == null)
    return;
  String s[] = sIn.split(",");
  if (s.length == 0)
    return;

  int angle = int(s[0]);
  int scanNum = (angle-minAngle)/angleStep;
  Scan scan = scans[scanNum];
  print("angle="+angle);
  for (int i=1; i<s.length && (i-1)<scan.points.length; i++) {
    String s1 = s[i].trim();
    if (s1.length() == 0)
      continue;
    int distance = int(s1);
    scan.points[i-1].setDistance(distance);
    print(", d"+i+"="+distance);
  }
  lastAngle = angle;
  if (angle < minAngle || angle > maxAngle) {
    println (" ---");
  } else {
    println ("");
  }
}
  • 6737