Trying to wrangle serial data from an Arduino

If anyone else would like to help, here’s my current Arduino code in full. It’s adapted from the version which prints stuff to the attached screen, so there’s a lot of commented out code.

// setup the screen and stuff
/*#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#define TFT_DC 6
#define TFT_CS 7
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);*/

//setup motor shield
#include <Adafruit_MotorShield.h>

//setup motors
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *aziDrive = AFMS.getStepper(200, 1);

//setup servos
#include <Servo.h>
Servo elevDrive;

//setup the sensor
#include <Wire.h>
#include <VL53L0X.h>
VL53L0X sensor;

//changeable variables are here
const int aziRange = 10; //azimuth total sweep range (in motor steps * aziRes (200 per 360 degrees))
const int aziRes = 1; //azimuth resolution
const int elevRange = 3; //elevation total sweep steps
const int elevRes = 4; //elevation resolution (in degrees) (make sure (elevRange*elevRes) <= 170)
const int numReadings = 2; //number of samples per scan
const float maxDepth = 1000.0; //maximum displayed depth (must have .0 to work)
//const float minDepth = 300.0; //minimum displayed depth (must have .0 to work)

//non-changeable setup variables are here
int LiDARdata[aziRange][elevRange];
//const int Height = 240;
//const int Width = 320;



void setup() {
  Serial.begin(9600);
  Wire.begin();
  while (!Serial);
  
  //Serial.println("Mini-LiDAR Program Start!");
  /*tft.begin();
  tft.setRotation(3);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.fillScreen(ILI9341_BLACK);*/

  elevDrive.attach(10); //attach the elevation servo to pin 10
  elevDrive.write(10);

  if(!AFMS.begin()) {
    //Serial.println("Could not find Motor Shield.");
    while (1);
  }
  //Serial.println("Motor Shield found.");

  sensor.setTimeout(500);
  if (!sensor.init()) {
    //Serial.println("Failed to detect and initialize sensor.");
    while (1) {}
  }
  //Serial.println("Sensor found.");

  sensor.startContinuous();
  
  //Serial.println("Initialization complete. Waiting for positioning.");
  //tft.print("Initialization complete. \nWaiting for positioning.");
  
  delay(3000); //wait for user to position the stepper

  aziDrive->setSpeed(1);
  aziDrive->step(aziRange/2, BACKWARD, MICROSTEP); //move motor back by half length to starting position

  //tft.fillScreen(ILI9341_BLACK);
  //tft.setRotation(1);
}



void loop() {
  elevDrive.write(10);
  for(int elevStep = 0; elevStep <= elevRange; elevStep++) {
    //Serial.print("Starting elevation sweep ");
    //Serial.println(elevStep);
    elevDrive.write((elevStep * elevRes) + 10); //elevate by a step and add 10 deg for power usage reasons (duplicated step to fix the second sweep not elevating bug)
    for (int aziStep = 0; aziStep < aziRange; aziStep++) {
      //Serial.println(aziStep);
      
      int total = 0;
      
      for(int i = 0; i < numReadings; i++) {
        total = total + sensor.readRangeContinuousMillimeters();
      }
      
      float average = (total/1.0)/(numReadings/1.0);
      //Serial.println(average);
      LiDARdata[aziStep][elevStep] = average; //store LiDAR data
      
      aziDrive->step(aziRes, FORWARD, MICROSTEP); //step azimuth forward by 1
    }
    //Serial.println("Azimuth moving back to start...");
    elevDrive.write(((elevStep + 1) * elevRes) + 10); //elevate by a step and add 10 deg for power usage reasons (added 1 to move during azimuth reset)
    aziDrive->step(aziRange*aziRes, BACKWARD, MICROSTEP); //move azimuth back to starting position
  }
  //Serial.println("Elevation moving back to start...");
  int elevStep = 0;
  elevDrive.write(elevStep + 10); //move elevation back to starting position
  
  for(int j = 0; j <= elevRange; ++j) { // loop through array's rows
    for(int i = 0; i < aziRange; ++i) {// loop through columns of current row
    /*
    float grayScale = 1; //this sets the grayScale value to 0 if the sensor reading was outside of the set maxDepth instead of it being that weird yellow color
    if (LiDARdata[i][j] < maxDepth) {
      grayScale = 1 - (LiDARdata[i][j] / maxDepth);
    } else {
      grayScale = 0;
    }
    //float grayScale = 1 - (LiDARdata[i][j] / maxDepth);
    //float grayScale = 1 - (((LiDARdata[i][j] - 0.0) * (maxDepth - minDepth) / (1300.0 - 0.0) + minDepth) / maxDepth);
    unsigned int colorHex = ((unsigned int)(0x1F * grayScale) << 11) \
                          | ((unsigned int)(0x3F * grayScale) << 5) \
                          |  (unsigned int)(0x1F * grayScale);
    
    tft.fillRect((i*(Width/aziRange)), (j*(Height/elevRange)), (Width/aziRange), (Height/elevRange), colorHex); //print data to screen in blocks
    */
    Serial.print(LiDARdata[i][j]); //print data to serial
    Serial.print("\t"); // start new column of output
    }
  Serial.print("\n"); // start new line of output
  }
  Serial.println("End");
  delay(1000);
}

Here’s my current attempt to read the serial data from the Arduino in Processing:

//MiniLiDAR companion display app
//pl4sma2389
//Credits to: GLV

import processing.serial.*;

Serial arduino; // Create object from Serial class
String serialData; // Data received from the serial port
int aziRange = 10; // Must be the same as on Arduino
int elevRange = 3; // Must be the same as on Arduino
int[][] LiDARdata = new int[aziRange][elevRange]; //Serial data formatted into an array
int data, count;
boolean dataSetReady;
int Width = 320;
int Height = 240;

void setup() {
  String portName = Serial.list()[2]; // 2 = COM3 = Arduino
  println();
  
  arduino = new Serial(this, portName, 9600);
  arduino.stop();
  arduino = new Serial(this, portName, 9600);
  
  size(Width, Height);
}

void draw() {
  if(arduino.available() > 0) {
    serialData = arduino.readStringUntil('\r');
    if(serialData != null) {
      serialData = trim(serialData);
      println(serialData);
      
      String[] dataIn = splitTokens(serialData, "\t");
      
      if(dataIn[2].equals("End")) {
        println();
        println("End");
        println();
        data = 0;
      }
    }
  }
}

And here’s my code to write some hand-formatted data to the screen in Processing:

int[][] LiDARdata = { {335, 478, 483, 467, 463, 443, 404, 411, 410, 385}, 
                      {455, 450, 445, 440, 435, 422, 412, 397, 389, 389}, 
                      {477, 474, 472, 462, 446, 429, 416, 412, 398, 392}, 
                      {478, 483, 467, 463, 443, 404, 411, 410, 385, 357} };
int aziRange = LiDARdata[0].length;
int elevRange = LiDARdata.length;
int Width = 320;
int Height = 240;
int maxRangeDisplayed = 500;

void settings() {
  size(Width, Height);
}

void setup() {
  frameRate(2);
  println(aziRange);
  println(elevRange);
}

void draw() {
  colorMode(RGB, maxRangeDisplayed, maxRangeDisplayed, maxRangeDisplayed);
  background(1);
  for (int i = 0; i < elevRange; i++) {
    for (int j = 0; j < aziRange; j++) {
      fill(maxRangeDisplayed - LiDARdata[i][j]);
      stroke(maxRangeDisplayed - LiDARdata[i][j]);
      rect((j*(Width/aziRange)), (i*(Height/elevRange)), (Width/aziRange), (Height/elevRange)); //print data to screen in blocks
    }
  }
}
1 Like