Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
mac70
Published © CC BY-NC-SA

Floating Display

This my DIY version of a floating display which shows information in mid-air.

IntermediateFull instructions providedOver 4 days4,073
Floating Display

Things used in this project

Story

Read more

Custom parts and enclosures

3d printed parts repository

also on Printables : https://www.printables.com/de/model/988031-parts-for-my-diy-floating-display

Code

Floating Display Sensor Subsystem Code (for Arduino Nano)

C/C++
sends distance reading from 3x VL530X TOF Sensors connected to Nano continously via UART (to the connected SBC). Also, a few basic commands can be processed from the SBC (e.g. RESET in case of errors).
/* 
  Floating Display Sensor Subsystem 

  Arduino NANO

  Triple VL53L0X TOF Sensors 
  Pins:
  VCC - VCC
  GND - GND
  SCL - A5
  SDA - A4
  XSHUT1 - D5 
  XSHUT2 - D6 
  XSHUT3 - D7 
  using the Polulo Library for VL53L0X because of less memory usage 
  
  Communication with Lattepanda via UART   

  V1 08.06.2024 initial version with second UART
  V2 11.06.2024 changed to main UART only, communication via USB-UART to Lattepanda (since VCC supply will be via USB)
  V3 28.06.2024 updated serial commands, added "display on" function via opto-coupler at startup
 
 */

#include <Wire.h>               // I2C bus library
#include <VL53L0X.h>            // TOF sensor Pololu library 

// I2C addresses for sensors
#define LOX1_ADDRESS 0x30
#define LOX2_ADDRESS 0x31
#define LOX3_ADDRESS 0x32

// sensor pins for shutdown
#define SHT_LOX1 5
#define SHT_LOX2 6
#define SHT_LOX3 7

// Pin controlling the external Display Module via Optocoupler
#define DISP_SWITCH 2

// 3 instances of sensors used
VL53L0X sensor1;
VL53L0X sensor2;
VL53L0X sensor3;

// Uncomment this line to use long range mode. This
//#define LONG_RANGE

// Uncomment ONE of these two lines to get
// - higher speed at the cost of lower accuracy OR
// - higher accuracy at the cost of lower speed
//#define HIGH_SPEED
//#define HIGH_ACCURACY

unsigned int distance1, distance2, distance3;   // values for the 3 sensor readings
boolean cmdreceived = false;    // true if new command received
String inputString = "";        // contains the received commandline

const unsigned int MIN_DISTANCE=600;    // set minimum distance for detection (600mm)

void setup()
{
  // init UART0
  Serial.begin(9600);
  Wire.begin();
  Serial.println(F("\n\nTriple VL53L0X Time of flight sensor unit"));
  Serial.println(F("========================================="));
  Serial.print(F("\nInitialize TOF sensors..."));

  pinMode(DISP_SWITCH, OUTPUT);
  digitalWrite(DISP_SWITCH, LOW);

  // Sequence to start all 3 sensors and give unique addresses on the same I2C bus :
  // all 3 sensors reset
  pinMode(SHT_LOX1, OUTPUT);
  digitalWrite(SHT_LOX1, LOW); // XSHUT pin low = reset
  pinMode(SHT_LOX2, OUTPUT);
  digitalWrite(SHT_LOX2, LOW);
  pinMode(SHT_LOX3, OUTPUT);
  digitalWrite(SHT_LOX3, LOW);  
  delay(20);
  // all unreset
  pinMode(SHT_LOX1, INPUT);  // XSHUT pin open (pulled high) = no reset
  pinMode(SHT_LOX2, INPUT);  
  pinMode(SHT_LOX3, INPUT);    
  delay(20);
  // sensor 1 unreset, resetting 2 + 3
  pinMode(SHT_LOX1, INPUT);  
  pinMode(SHT_LOX2, OUTPUT);
  digitalWrite(SHT_LOX2, LOW);
  pinMode(SHT_LOX3, OUTPUT);
  digitalWrite(SHT_LOX3, LOW);
  // activating sensor 1 
  sensor1.setAddress(LOX1_ADDRESS);
  sensor1.setTimeout(500);
  if (!sensor1.init())
  {
    Serial.println("\n->ERROR. Failed to detect and initialize sensor1 !");
    while (1) {}
  }
  // activating sensor 2
  pinMode(SHT_LOX2, INPUT);  // pin open (pulled high), no reset
  delay(20);
  sensor2.setAddress(LOX2_ADDRESS);
  sensor2.setTimeout(500);
  if (!sensor2.init())
  {
    Serial.println("\n->ERROR. Failed to detect and initialize sensor2 !");
    while (1) {}
  }
  // activating sensor 3
  pinMode(SHT_LOX3, INPUT);  // pin open (pulled high), no reset
  delay(20);
  sensor3.setAddress(LOX3_ADDRESS);
  sensor3.setTimeout(500);
  if (!sensor3.init())
  {
    Serial.println("\n->ERROR. Failed to detect and initialize sensor3 !");
    while (1) {}
  }
 

#if defined LONG_RANGE
  // lower the return signal rate limit (default is 0.25 MCPS)
  sensor1.setSignalRateLimit(0.1);
  // increase laser pulse periods (defaults are 14 and 10 PCLKs)
  sensor1.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
  sensor1.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
#endif

#if defined HIGH_SPEED
  // reduce timing budget to 20 ms (default is about 33 ms)
  sensor1.setMeasurementTimingBudget(20000);
#elif defined HIGH_ACCURACY
  // increase timing budget to 200 ms
  sensor1.setMeasurementTimingBudget(200000);
#endif

  Serial.println(F("OK, all sensors initialized."));

  // automatically switch on external display after each reset (note : if it's on already, no effect)
  Serial.print(F("Switching on external display module..."));
  digitalWrite(DISP_SWITCH, HIGH);    // open opto-coupler "switch"
  delay(2500);                        // keep switch pressed...
  digitalWrite(DISP_SWITCH, LOW);     // close again 
  Serial.println(F("done."));

  Serial.println(F("->SENSOR UNIT READY."));

}

void loop()
{

  distance3 = sensor1.readRangeSingleMillimeters();
  distance2 = sensor2.readRangeSingleMillimeters();
  distance1 = sensor3.readRangeSingleMillimeters();

  if (distance1 < MIN_DISTANCE)   
  {
   Serial.print("A:");
   Serial.print(distance1);
   Serial.println(";");
  }
  if (distance2 < MIN_DISTANCE)
  {
   Serial.print("B:");
   Serial.print(distance2);
   Serial.println(";");
  }
  if (distance3 < MIN_DISTANCE)
  {
   Serial.print("C:");
   Serial.print(distance3);
   Serial.println(";");
  }

  if (sensor1.timeoutOccurred()) { Serial.println(F("->ERROR Timeout Sensor1 !")); }
  if (sensor2.timeoutOccurred()) { Serial.println(F("->ERROR Timeout Sensor2 !")); }
  if (sensor3.timeoutOccurred()) { Serial.println(F("->ERROR Timeout Sensor3 !")); }

  if (Serial.available() > 0) processInput(); // process serial commands

}

void(* resetFunc) (void) = 0;//declare reset function at address 0

/* --------------------------------------------------------------------------------------
Process Input -> Called from main() when serial characters have been received
-------------------------------------------------------------------------------------- */
void processInput() 
{
  while (Serial.available())   // process all characters in input buffer received 
  {
    char inChar = (char)(Serial.read());  // read next character
    if (inChar == '\n')                   // Line-Feed received ?
    {
     // --------------------------------------
     // commands :
     // display module ON/OFF
     if (inputString.startsWith("DISPON"))
     {
         Serial.println(F("->DISPLAY MODULE ON"));
         digitalWrite(DISP_SWITCH, HIGH);
         delay(2500);  // keep switch pressed...
         digitalWrite(DISP_SWITCH, LOW);

     }
     // reset
     if (inputString.startsWith("RESET"))
     {
         Serial.println(F("->SENSOR MODULE RESET"));
         resetFunc(); //call reset   
     }
     // --------------------------------------
     // ready for next command
     Serial.println(F("\n"));
     inputString = "";     
    }
    else
    {
       inputString += inChar;             // no, add chat to inputString 
       Serial.print(inChar);              // Echo 
    }
  }
}



 

Credits

mac70

mac70

6 projects • 36 followers

Comments