XRAD'S Lidar Timer Sphero Wrist Band

Please tell us which board you are using.
For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
XRAD
 
Posts: 754
Joined: Sat Nov 19, 2016 3:28 pm

XRAD'S Lidar Timer Sphero Wrist Band

Post by XRAD »

Hi All, Another weekend build. Soooo...Amazon has the Sphero force band for 10$ or so...wayyyy cheaper than a year ago. I saw this and said "hmmm...let's do something with it." The Sphero band has a really nice board, with charger, and sound and force sensor and bluetooth..but I could not hack it, so I cut it up and used parts to make my own band. My band has a cool lidar screen, a random integer force shield, and a stopwatch timer accurate to 1 second every 10 minutes. Also included a Lipo charger in the build.....

And I have to say that my new go to board for my little projects was the Teensy 3.2..but now I LOVE the Adafruit Itsybitsy M4 w/atsam51. This board has a rock solid USB connection on win 11. It processes my cos/sin arc code very quickly, and in doing so, can draw my radius scan lines VERY quickly and fluidly. Tried it on trinket M0, and it failed to display parts of the sweep code.

Also, I found this little SD player: DFRobot SD mini player (https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299) . It is a GREAT little board. Uses micro SD, has a tiny footprint, easy C++ code, and has it's own 3w amp. This is an easy board to use. Just download the DFRobot github code for arduino. the only issue was the 'loop' track does not work. No big deal. I only need a few sounds here and there. It takes 200ms to activate a track, so you have to be patient with your code. Also, be VERY careful the way you close your SD card once files loaded. Always use 'eject' because any tiny bit of corruption, and the DFRobot player will have issues playing your tracks. You do not need a folder, just load your SD tracks as 001.mytrack, etc... Also, be sure to purchase the original version DFRobot player, not the amazon knock-offs (same for Adafruit products!).

for the OLED, I use U8g2lib.h This is an excellent easy to use library. Tons of fonts built in. Branches adafruit gfx code, so you can use many of the same functions...

Short vid at:
https://www.youtube.com/watch?v=C31zMyfmmgQ

Hardware:
Adafruit ItsyBitsy M4
Pololu Mini pushbutton switch 2808
3w 30mm speaker
DFRobot SD mini player
Lighted mini pushbutton TL1265BQSCLR x 3
850mAh lipo battery 45x25x9mm (you can get x4 and charger for only a few $'s)
I2C Display Module 0.91 Inch I2C OLED Display


Here is my code. I don't know what happened to adafruit's pop-out code box, so you will have to scroll through 360 or so lines to find everything. There are a few neat lines. Also, I used an interrupt, a millis timer, and some other things some of you may find useful. Use/modify as you like!

Code: Select all

#include <Adafruit_DotStar.h>
#include <U8g2lib.h>
#include "DFRobotDFPlayerMini.h"

DFRobotDFPlayerMini myDFPlayer;

#define NUMPIXELS 1
//Use these pin definitions for the ItsyBitsy M4
#define DATAPIN    8
#define CLOCKPIN   6


const int widthOLED = 128;
const int heightOLED = 32;
const int rBeam = 50;//radar beam radius

const int ledInterruptPin = A2;
const int ledReset = A3;
const int ledLidar = A4;

const int interruptPin = 9;
volatile int state = LOW;

//timer variables
int milliseconds = 0;
int seconds = 0;
int minutes = 0;
int hours = 0;
const int resetPin = 7;


// global millis variables
unsigned long startMillis;
unsigned long currentMillis;
const int period = 100;
unsigned long decisecond = 0;

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0);

Adafruit_DotStar strip(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_GBR);

uint32_t magenta = strip.Color(255, 255, 0);

void testRects() {//modified from adafruit gfx
  int n, i, i2, x, cx = widthOLED  / 2, cy = heightOLED / 2;
  n = max( widthOLED , heightOLED);
  for ( x = 0; x < 1; x++) {
    for (i = 2; i < n; i += 12) {
      i2 = i / 2;
      u8g2.drawFrame(cx - i2, cy - i2, i, i);
      u8g2.sendBuffer();
      delay(100);
    }
    u8g2.clearBuffer();
  }
}

void drawBigFont() {
  myDFPlayer.play(2);
  u8g2.setDrawColor(1);// blue
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_logisoso28_tr);  // choose a suitable font at https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.drawStr(8, 29, "LIDAR"); // write something to the internal memory
  u8g2.sendBuffer();         // transfer internal memory to the display
  delay(750);
  u8g2.clearBuffer();         // clear the internal memory
  u8g2.setFont(u8g2_font_logisoso28_tr);  // choose a suitable font at https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.drawStr(10, 29, "ACTIVE"); // write something to the internal memory
  u8g2.sendBuffer();         // transfer internal memory to the display
  delay(750);
  myDFPlayer.play(3);
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_logisoso28_tr);  // choose a suitable font at https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.drawStr(8, 29, "SHIELD"); // write something to the internal memory
  u8g2.sendBuffer();         // transfer internal memory to the display
  delay(750);
  u8g2.clearBuffer();         // clear the internal memory
  u8g2.setFont(u8g2_font_logisoso28_tr);  // choose a suitable font at https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.drawStr(10, 29, "ACTIVE"); // write something to the internal memory
  u8g2.sendBuffer();         // transfer internal memory to the display
  delay(750);
}


void  drawRadarScreen() {
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_micro_tr);
  char loadA[] = "  LIDAR ";
  for (int p = 0; p < strlen(loadA) ; p++) {
    char c = loadA[p];
    loadA[p] = '\n';
    u8g2.drawStr(2, 5, loadA); // write something to the internal memory
    loadA[p] = c;
    u8g2.sendBuffer();          // transfer internal memory to the display
    delay(10);
  }

  char loadB[] = "ACTIVE ";
  for (int p = 0; p < strlen(loadB) ; p++) {
    char c = loadB[p];
    loadB[p] = '\n';
    u8g2.drawStr(105, 5, loadB); // write something to the internal memory
    loadB[p] = c;
    u8g2.sendBuffer();          // transfer internal memory to the display
    delay(10);
  }

  for (int j = 0; j < 3; j++) {
    myDFPlayer.play(4);
    digitalWrite(ledLidar, HIGH);
    for ( int i = -180; i > (-360); i = i - 5 ) {//set the degrees according to OLED '0', and for CW or CCW
      u8g2.setDrawColor(1);// Blue
      u8g2.drawLine(0, 31, widthOLED , 31);
      u8g2.drawLine(widthOLED / 2, 0, widthOLED / 2, 31);
      u8g2.drawCircle(widthOLED / 2, 30, 10);
      u8g2.drawCircle(widthOLED / 2, 30, 20);
      u8g2.drawCircle(widthOLED / 2, 30, 30);
      u8g2.drawCircle(widthOLED / 2, 30, 40);
      u8g2.drawCircle(widthOLED / 2, 30, 50);
      u8g2.drawLine( widthOLED / 2,  30,  widthOLED / 2 + rBeam * cos( ( 360 - i ) * 3.14 / 180 ), 30  + rBeam * sin( ( 360 - i ) * 3.14 / 180 ) );
      u8g2.sendBuffer();
      u8g2.setDrawColor(0);// Black
      u8g2.drawLine( widthOLED / 2,  30,  widthOLED / 2 + rBeam * cos( ( 360 - i ) * 3.14 / 180 ), 30   + rBeam * sin( ( 360 - i ) * 3.14 / 180 ) );
      u8g2.sendBuffer();
      if (i >= -210) {
        digitalWrite(ledLidar, LOW);
      }
    }
    myDFPlayer.play(4);
    digitalWrite(ledLidar, HIGH);
    for ( int i = -360; i < -180; i = i + 5 ) {
      u8g2.setDrawColor(1);// Blue
      u8g2.drawLine(0, 31, widthOLED , 31);
      u8g2.drawLine(widthOLED / 2, 0, widthOLED / 2, 31);
      u8g2.drawCircle(widthOLED / 2, 30, 10);
      u8g2.drawCircle(widthOLED / 2, 30, 20);
      u8g2.drawCircle(widthOLED / 2, 30, 30);
      u8g2.drawCircle(widthOLED / 2, 30, 40);
      u8g2.drawCircle(widthOLED / 2, 30, 50);
      u8g2.drawLine( widthOLED / 2,  30,  widthOLED / 2 + rBeam * cos( ( 360 - i ) * 3.14 / 180 ), 30  + rBeam * sin( ( 360 - i ) * 3.14 / 180 ) );
      u8g2.sendBuffer();
      u8g2.setDrawColor(0);// Black
      u8g2.drawLine( widthOLED / 2,  30,  widthOLED / 2 + rBeam * cos( ( 360 - i ) * 3.14 / 180 ), 30   + rBeam * sin( ( 360 - i ) * 3.14 / 180 ) );
      u8g2.sendBuffer();
      if (i <= -330) {
        digitalWrite(ledLidar, LOW);
      }
    }
  }
}

void loadScreen() {//different fonts screen one char at a time
  u8g2.setDrawColor(1);// Blue, (0) = black
  u8g2.drawFrame(0, 0, 128, 32);
  u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
  char load[] = "LOADING......DONE..";
  for (int p = 0; p < strlen(load) ; p++) {
    char c = load[p];
    load[p] = '\n';
    u8g2.drawStr(5, 10, load); // write something to the internal memory
    load[p] = c;
    u8g2.sendBuffer();          // transfer internal memory to the display
    delay(0);
  }

  u8g2.setFont(u8g2_font_micro_tr);
  char load1[] = "SCANNING RANGE: 2000 meters ";
  for (int p = 0; p < strlen(load1) ; p++) {
    char c = load1[p];
    load1[p] = '\n';
    u8g2.drawStr(5, 20, load1); // write something to the internal memory
    load1[p] = c;
    u8g2.sendBuffer();          // transfer internal memory to the display
    delay(0);
  }

  //u8g2.setFont(u8g2_font_u8glib_4_tr); // choose a suitable font
  char load2[] = "SHIELD:Random Shield Integer ";
  for (int p = 0; p < strlen(load2) ; p++) {
    char c = load2[p];
    load2[p] = '\n';
    u8g2.drawStr(5, 30, load2); // write something to the internal memory
    load2[p] = c;
    u8g2.sendBuffer();          // transfer internal memory to the display
    delay(0);
  }
  delay(3000);
  u8g2.clearBuffer();
}

void randNum() {
  myDFPlayer.play(5);
  u8g2.setDrawColor(1);// blue
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_logisoso28_tr);  // choose a suitable font at https://github.com/olikraus/u8g2/wiki/fntlistall
  u8g2.setCursor(1, 29);
  for (int i = 0; i < 7; i++) {
    int a;
    a = random(0 - 9);
    u8g2.print(a);
    delay(35);
    u8g2.sendBuffer();
  }
  delay(1000);
  u8g2.clearBuffer();
}

void clockTimer() {
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_logisoso28_tr);
  setClock();
  u8g2.setCursor(1, 29);

  if (minutes < 10) {
    u8g2.print("0");//place holder
    u8g2.print(minutes);
    u8g2.print(":");
  }
  else {
    u8g2.print(minutes);
    u8g2.print(":");
  }

  if (seconds < 10) {
    u8g2.print("0");
    u8g2.print(seconds);
    u8g2.print(":");
  }
  else {
    u8g2.print(seconds);
    u8g2.print(":");
  }

  if (decisecond < 10) {
    u8g2.print("0");
    u8g2.print(decisecond);
  }
  else {
    u8g2.print(decisecond);
  }
  u8g2.sendBuffer();
}



void setClock() {
  if (decisecond > 90) { //whenever deciseconds is greater than 90), deciseconds = 0, and add 1 to seconds
    decisecond = 0;
    seconds++;
  }
  if (seconds > 59) {
    seconds = 0;    //whenever seconds is greater than 59, second = 0, and add 1 to minutes
    myDFPlayer.play(6);// tick every minute
    minutes++;
  }
  if (minutes > 59) {
    u8g2.clearBuffer();
    u8g2.drawStr(1, 29, "RESET");
    u8g2.sendBuffer();
    minutes = 0;
    delay(1000);
  }
}


void clearClockTimer() {
  myDFPlayer.play(6);
  digitalWrite(ledReset, HIGH);
  u8g2.clearBuffer();
  u8g2.drawStr(1, 29, "RESET");
  decisecond = 0;
  seconds = 0;
  minutes = 0;
  u8g2.sendBuffer();
  delay(1000);
  digitalWrite(ledReset, LOW);
}


void blink() {
  state = !state;
  //Serial.println("button");
  if (state) {
    digitalWrite(ledInterruptPin, HIGH);
  }
  if (!state) {
    digitalWrite(ledInterruptPin, LOW);
  }
}


void setup(void) {

  Serial.begin(115200);
  Serial1.begin(9600);
  u8g2.begin();
  myDFPlayer.begin(Serial1);
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);//not sure if this is needed....
  //myDFPlayer.EQ(4);//10 selections
  myDFPlayer.volume(23);//0-30
  randomSeed(analogRead(20));//for randNum generator

  pinMode(ledReset, OUTPUT);// reset timer led
  pinMode(ledLidar, OUTPUT);//lidar flash led
  pinMode(ledInterruptPin, OUTPUT);//turn on when interrupt flagged

  pinMode(resetPin, INPUT_PULLUP);
  pinMode(interruptPin, INPUT_PULLUP);//interruptPin to ground
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);//works better than CHANGE
  //attachInterrupt(interruptPin, blink, CHANGE);//works with M4(samd51)
  strip.begin(); // Initialize pins for output
  /*
    strip.setPixelColor(0, 0xFF0000); // red
    strip.show();
    delay(1000);

    strip.setPixelColor(0, 0x00FF00); // green
    strip.show();
    delay(1000);

    strip.setPixelColor(0, 0x0000FF); // blue
    strip.show();
    delay(1000);
  */
  strip.setBrightness(0);//(80);
  strip.fill(0, 0, 0);
  strip.show();
  delay(250);//df mini sd needs a bit of boot time

  myDFPlayer.play(1);
  delay(10000); // that's how long boot track is

  drawBigFont();
  u8g2.clearBuffer();
  loadScreen();
  u8g2.clearBuffer();
  myDFPlayer.play(5);
  testRects();
  u8g2.clearBuffer();
}

void loop(void) {
  if (state) {//non blocking code
    int buttonState = digitalRead(resetPin);
    if (buttonState == LOW) {
      clearClockTimer();
    }
    else {
      currentMillis = millis();  //get the current "time"...the number of milliseconds since boot
      if (currentMillis - startMillis >= period)  //has period elapsed? do something
      { decisecond = decisecond + 10;//add '1 / 10th' second to timer
        clockTimer();
        startMillis = currentMillis;  //reset start counter
      }
    }
  }

  if (!state) { //blocking code
    drawRadarScreen();
    u8g2.clearBuffer();
    randNum();
    u8g2.clearBuffer();
  }
}
Build pics:
on the wrist....
on the wrist....
small 5.JPG (54.95 KiB) Viewed 180 times
on the breadboard first
on the breadboard first
small 3.JPG (96.54 KiB) Viewed 180 times
tight wiring
tight wiring
small 4.JPG (86.49 KiB) Viewed 180 times
Last edited by XRAD on Sun Aug 28, 2022 6:03 pm, edited 3 times in total.

User avatar
XRAD
 
Posts: 754
Joined: Sat Nov 19, 2016 3:28 pm

Re: XRAD'S Lidar Time Sphero Wrist Band

Post by XRAD »

more pics:
small 6.JPG
small 6.JPG (72.93 KiB) Viewed 175 times
small 7.JPG
small 7.JPG (72.44 KiB) Viewed 175 times
USB charger, charger leds light up and you can see if charging or charged in the tan doughnut!
USB charger, charger leds light up and you can see if charging or charged in the tan doughnut!
small 8.JPG (69.2 KiB) Viewed 175 times

Locked
Please be positive and constructive with your questions and comments.

Return to “Itsy Bitsy Boards”