The Alpha Geek – Geeking Out

NeoPixel Stick

Project #19: Time – NeoPixel Stick – 8 – Mk11

——

#DonLucElectronics #DonLuc #Time #EMF #IMU #NeoPixel #RTC #Display #Adalogger #MicroSD #GPSReceiver #CCS811 #BME280 #Arduino #ESP32 #Project #Programming #Electronics #Microcontrollers #Consultant #VideoBlog

——

NeoPixel Stick

——

NeoPixel Stick

——

NeoPixel Stick

——

NeoPixel Stick

——

Pololu Adjustable Step-Up Voltage Regulator U1V11A

This compact U1V11A switching step-up voltage regulator efficiently boosts input voltages as low as 0.5 V to an adjustable output voltage between 2 V and 5.25 V. Unlike most boost regulators, the U1V11A offers a true shutdown option that turns off power to the load, and it automatically switches to a linear down-regulation mode when the input voltage exceeds the output. The pins have a 0.1 inch spacing, making this board compatible with standard solderless breadboards.

NeoPixel Stick – 8 x 5050 RGB LED

Make your own little LED strip arrangement with this stick of NeoPixel LEDs. We crammed 8 of the tiny 5050 (5mm x 5mm) smart RGB LEDs onto a PCB with mounting holes and a chainable design. Use only one microcontroller pin to control as many as you can chain together! Each LED is addressable as the driver chip is inside the LED. Each one has ~18mA constant current drive so the color will be very consistent even if the voltage varies, and no external choke resistors are required making the design slim. Power the whole thing with 5VDC.

DL2109Mk02

1 x SparkFun Thing Plus – ESP32 WROOM
1 x Adafruit SHARP Memory Display
1 x Adalogger FeatherWing – RTC + SD
1 x SparkFun Environmental Combo CCS811/BME280 (Qwiic)
1 x Pololu MinIMU-9
1 x Telescopic Antenna SMA – 300 MHz to 1.1 GHz (ANT700)
1 x SMA Connector
1 x NeoPixel Stick – 8 x 5050 RGB LED
1 x Pololu Adjustable Step-Up Voltage Regulator U1V11A
1 x CR1220 3V Lithium Coin Cell Battery
1 x 32Gb microSD Card
1 x LED Green
1 x Rocker Switch – SPST (Round)
1 x Terminal Block Breakout FeatherWing
1 x Lithium Ion Battery – 850mAh
1 x GPS Receiver – GP-20U7
1 x Rotary Switch – 10 Position
1 x SparkFun Rotary Switch – 10 Position
1 x Black Knob
2 x Spring Terminals – PCB Mount (6-Pin)
2 x Screw Terminals 5mm Pitch (2-Pin)
2 x Breadboard Solderable
12 x 1K Ohm
1 x 3.3m Ohm
1 x FeatherWing Proto
1 x Acrylic Orange 5.75 inches x 3.75 inches x 1/8 inch
1 x Acrylic Black 5.75 inches x 3.75 inches x 1/8 inch
54 x Screw – 4-40
19 x Standoff – Metal 4-40 – 3/8″
8 x Standoff – Metal 4-40 – 1″
1 x SparkFun Cerberus USB Cable

SparkFun Thing Plus – ESP32 WROOM

NEO – Digital 15
SCK – Digital 13
MSI – Digital 12
SS0 – Digital 27
GRX – Digital 16
GTX – Digital 17
SDA – Digital 23
SDL – Digital 22
SCK – Digital 5
MSO – Digital 19
MSI – Digital 18
SS1 – Digital 33
LEG – Digital 21
SW0 – Digital 32
ROT – Analog A0
EMF – Analog A1
VIN – +3.3V
GND – GND

——

DL2109Mk02p.ino

/* 
***** Don Luc Electronics © *****
Software Version Information
Project #19: Time - NeoPixel Stick - 8 - Mk11
09-02
DL2109Mk02p.ino
1 x SparkFun Thing Plus - ESP32 WROOM
1 x Adafruit SHARP Memory Display
1 x Adalogger FeatherWing - RTC + SD
1 x SparkFun Environmental Combo CCS811/BME280 (Qwiic)
1 x Pololu MinIMU-9
1 x Telescopic Antenna SMA - 300 MHz to 1.1 GHz (ANT700)
1 x SMA Connector
1 x NeoPixel Stick - 8 x 5050 RGB LED
1 x Pololu Adjustable Step-Up Voltage Regulator U1V11A
1 x CR1220 3V Lithium Coin Cell Battery
1 x 32Gb microSD Card
1 x LED Green
1 x Rocker Switch - SPST (Round)
1 x Terminal Block Breakout FeatherWing
1 x Lithium Ion Battery - 850mAh
1 x GPS Receiver - GP-20U7
1 x Rotary Switch - 10 Position
1 x SparkFun Rotary Switch – 10 Position
1 x Black Knob
2 x Spring Terminals - PCB Mount (6-Pin)
2 x Screw Terminals 5mm Pitch (2-Pin)
2 x Breadboard Solderable
12 x 1K Ohm
1 x 3.3m Ohm
1 x FeatherWing Proto
1 x Acrylic Orange 5.75 inches x 3.75 inches x 1/8 inch
1 x Acrylic Black 5.75 inches x 3.75 inches x 1/8 inch
54 x Screw - 4-40
19 x Standoff - Metal 4-40 - 3/8"
8 x Standoff - Metal 4-40 - 1"
1 x SparkFun Cerberus USB Cable
*/

// Include the Library Code
// EEPROM Library to Read and Write EEPROM with Unique ID for Unit
#include "EEPROM.h"
// Wire
#include <Wire.h>
// SHARP Memory Display
#include <Adafruit_SharpMem.h>
#include <Adafruit_GFX.h>
// Date and time RTC
#include "RTClib.h"
// GPS Receiver
#include <TinyGPS++.h>
// ESP32 Hardware Serial
#include <HardwareSerial.h>
// SD Card
#include "FS.h"
#include "SD.h"
#include "SPI.h"
// SparkFun CCS811 - eCO2 & tVOC
#include <SparkFunCCS811.h>
// SparkFun BME280 - Humidity, Temperature, Altitude and Barometric Pressure
#include <SparkFunBME280.h>
// 9DoF IMU
// STMicroelectronics LSM6DS33
#include <LSM6.h>
// STMicroelectronics LIS3MDL
#include <LIS3MDL.h>
// NeoPixels
#include <Adafruit_NeoPixel.h>

// SHARP Memory Display
#define SHARP_SCK  13
#define SHARP_MOSI 12
#define SHARP_SS   27
// Set the size of the display here, e.g. 144x168!
Adafruit_SharpMem display(SHARP_SCK, SHARP_MOSI, SHARP_SS, 144, 168);
// The currently-available SHARP Memory Display (144x168 pixels)
// requires > 4K of microcontroller RAM; it WILL NOT WORK on Arduino Uno
// or other <4K "classic" devices.
#define BLACK 0
#define WHITE 1

// Date and Time
// PCF8523 Precision RTC 
RTC_PCF8523 rtc;
// Date
String dateRTC = "";
// Time
String timeRTC = "";

// ESP32 HardwareSerial
HardwareSerial tGPS(2);

// GPS Receiver
#define gpsRXPIN 16
// This one is unused and doesnt have a conection
#define gpsTXPIN 17
// The TinyGPS++ object
TinyGPSPlus gps;
// Latitude
float TargetLat;
// Longitude
float TargetLon;
// GPS Date, Time, Speed, Altitude
// GPS Date
String TargetDat;
// GPS Time
String TargetTim;
// GPS Speeds M/S
String TargetSMS;
// GPS Speeds Km/h
String TargetSKH;
// GPS Altitude Meters
String TargetALT;
// GPS Status
String GPSSt = "";

// Rotary Switch - 10 Position
// Number 1 => 10
int iRotNum = A0;
// iRotVal - Value 
int iRotVal = 0;
// Number
int z = 0;

// MicroSD Card
const int chipSelect = 33;
String zzzzzz = "";

// LED Green
int iLEDGreen = 21;

// Rocker Switch - SPST (Round)
int iSS1 = 32;
// State
int iSS1State = 0;

// SparkFun CCS811 - eCO2 & tVOC
// Default I2C Address
#define CCS811_ADDR 0x5B 
CCS811 myCCS811(CCS811_ADDR);
// eCO2
float CCS811CO2 = 0;
// TVOC
float CCS811TVOC = 0;

// SparkFun BME280 - Temperature, Humidity, Altitude and Barometric Pressure
BME280 myBME280;
// Temperature Celsius
float BMEtempC = 0;
// Humidity
float BMEhumid = 0;
// Altitude Meters
float BMEaltitudeM = 0;
// Barometric Pressure
float BMEpressure = 0;

// 9DoF IMU
// STMicroelectronics LSM6DS33
LSM6 imu;
// // Accelerometer and Gyroscopes
// Accelerometer
int imuAX;
int imuAY;
int imuAZ;
// Gyroscopes
int imuGX;
int imuGY;
int imuGZ;
// STMicroelectronics LIS3MDL
LIS3MDL mag;
// Magnetometer
int magX;
int magY;
int magZ;

// NeoPixels
// On digital pin 15
#define PIN 15
// NeoPixels NUMPIXELS = 8
#define NUMPIXELS 8
// Pixels
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
// Red
int red = 0;
// Green
int green = 0;
// Blue
int blue = 0;
// Neopix
int iNeo = 0;
// Value
int zz = 0;

// EMF Meter (Single Axis)
int iEMF = A1;
// Raise this number to increase data smoothing
#define NUMREADINGS 15
// Raise this number to decrease sensitivity (up to 1023 max)
int senseLimit = 15;
// EMF Value
int val = 0;
// Readings from the analog input
int readings[ NUMREADINGS ];
// Index of the current reading
int indexEMF = 0;
// Running total
int totalEMF = 0;
// Final average of the probe reading
int averageEMF = 0;
// Display EMF
int iEMFDis = 0;
int iEMFRect = 0;

// Software Version Information
// EEPROM Unique ID Information
#define EEPROM_SIZE 64
String uid = "";
// Version
String sver = "19-11";

void loop()
{
     
  // Dates and Time
  isRTC();

  // isGPS
  isGPS();

  // SparkFun BME280 - Temperature, Humidity, Altitude and Barometric Pressure
  isBME280();

  // SparkFun CCS811 - eCO2 & tVOC
  isCCS811();

  // Accelerometer and Gyroscopes
  isIMU();

  // Magnetometer
  isMag();

  // EMF Meter (Single Axis)
  isEMF();

  // Rotary Switch
  isRot();

  // Slide Switch
  // Read the state of the iSS1 value
  iSS1State = digitalRead(iSS1);
  
  // If it is the Slide Switch State is HIGH
  if (iSS1State == HIGH) {

    // iLEDGreen HIGH
    digitalWrite(iLEDGreen,  HIGH );
    
    // MicroSD Card
    isSD();

  } else {

    // iLEDGreen LOW
    digitalWrite(iLEDGreen,  LOW );
  
  }

  delay( 1000 );
 
}

getAccelGyro.ino

// Accelerometer and Gyroscopes
// Setup IMU
void setupIMU() {

  // Setup IMU
  imu.init();
  // Default
  imu.enableDefault();
  
}
// Accelerometer and Gyroscopes
void isIMU() {

  // Accelerometer and Gyroscopes
  imu.read();
  // Accelerometer x, y, z
  imuAX = imu.a.x;
  imuAY = imu.a.y;
  imuAZ = imu.a.z;
  // Gyroscopes x, y, z
  imuGX = imu.g.x;
  imuGY = imu.g.y;
  imuGZ = imu.g.z;

}

getBME280.ino

// SparkFun BME280 - Temperature, Humidity, Altitude and Barometric Pressure
// isBME280 - Temperature, Humidity, Altitude and Barometric Pressure
void isBME280(){

  // Temperature Celsius
  BMEtempC = myBME280.readTempC();
  // Humidity
  BMEhumid = myBME280.readFloatHumidity();
  // Altitude Meters
  BMEaltitudeM = (myBME280.readFloatAltitudeMeters(), 2);
  // Barometric Pressure
  BMEpressure = myBME280.readFloatPressure();
  
}

getCCS811.ino

// CCS811 - eCO2 & tVOC
// isCCS811 - eCO2 & tVOC
void isCCS811(){

  // This sends the temperature & humidity data to the CCS811
  myCCS811.setEnvironmentalData(BMEhumid, BMEtempC);

  // Calling this function updates the global tVOC and eCO2 variables
  myCCS811.readAlgorithmResults();

  // eCO2 Concentration
  CCS811CO2 = myCCS811.getCO2();
  
  // tVOC Concentration
  CCS811TVOC = myCCS811.getTVOC();
  
}

getDisplay.ino

// SHARP Memory Display
// SHARP Memory Display - UID
void isDisplayUID() {

    // Text Display 
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(3);
    display.setTextColor(BLACK);
    // Don Luc Electronics
    display.setCursor(0,10);
    display.println( "Don Luc" );
    display.setTextSize(2);
    display.setCursor(0,40);
    display.println( "Electronics" );
    // Version
    //display.setTextSize(3);
    display.setCursor(0,70);
    display.println( "Version" );
    //display.setTextSize(2);
    display.setCursor(0,95);   
    display.println( sver );
    // EEPROM
    display.setCursor(0,120);
    display.println( "EEPROM" );
    display.setCursor(0,140);   
    display.println( uid );
    // Refresh
    display.refresh();
    delay( 100 );
    
}
// Display Date
void isDisplayDate() {

    // Text Display Date
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(2);
    display.setTextColor(BLACK);
    // Date
    display.setCursor(0,5);
    display.println( "Date" );
    display.setCursor(0,30);
    display.println( dateRTC );
    // Time
    display.setCursor(0,55);
    display.println( "Time" );
    display.setCursor(0,75);
    display.println( timeRTC );
    // Refresh
    display.refresh();
    delay( 100 );

}
// Display GPS
void isDisplayGPS() {

    // Text Display Date
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(2);
    display.setTextColor(BLACK);
    // GPS Status
    display.setCursor(0,5);
    display.print( "GPS: " );
    display.println( GPSSt );
    // Target Latitude
    display.setCursor(0,25);
    display.println( "Latitude" );
    display.setCursor(0,45);
    display.println( TargetLat );
    // Target Longitude
    display.setCursor(0,65);
    display.println( "Longitude" );
    display.setCursor(0,90);
    display.println( TargetLon );
    // Refresh
    display.refresh();
    delay( 100 );

}
// GPS Date, Time, Speed, Altitude
void isDisplayGPSDate() {

    // Text Display Date
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(2);
    display.setTextColor(BLACK);
    // GPS
    display.setCursor(0,5);
    display.println( "GPS" );
    // Date
    display.setCursor(0,30);
    display.println( TargetDat );
    // Time
    display.setCursor(0,55);
    display.println( TargetTim );
    // Speed
    display.setCursor(0,75);
    display.print( "M/S: " );
    display.println( TargetSMS );
    display.setCursor(0,95);
    display.print( "Km/h: " );
    display.println( TargetSKH );
    display.setCursor(0,115);
    display.print( "Alt: " );
    display.println( TargetALT );
    // Refresh
    display.refresh();
    delay( 100 );

}
// Display SparkFun BME280 - Temperature, Humidity, Altitude and Barometric Pressure
void isDisplayBME280() {

     // Text Display BME280
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(2);
    display.setTextColor(BLACK);
    // Temperature Celsius
    display.setCursor(0,5);
    display.println( "Temperature" );
    display.setCursor(0,25);
    display.print( BMEtempC );
    display.println( " C" );
    // Humidity
    display.setCursor(0,45);
    display.println( "Humidity" );
    display.setCursor(0,65);
    display.print( BMEhumid );
    display.println( "%" );
    // Altitude Meters
    display.setCursor(0,85);
    display.println( "Altitude M" );
    display.setCursor(0,105);
    display.print( BMEaltitudeM );
    display.println( " m" );
    // Pressure
    display.setCursor(0,125);    
    display.println( "Barometric" );
    display.setCursor(0,145);
    display.print( BMEpressure );
    display.println( "Pa" );
    // Refresh
    display.refresh();
    delay( 100 );

}
// Display CCS811 - eCO2 & tVOC
void isDisplayCCS811() {

    // Text Display CCS811
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(2);
    display.setTextColor(BLACK);
    // eCO2 Concentration
    display.setCursor(0,5);
    display.println( "eCO2" );
    display.setCursor(0,25);
    display.print( CCS811CO2 );
    display.println( " ppm" );
    // tVOC Concentration
    display.setCursor(0,55);
    display.println( "tVOC" );
    display.setCursor(0,75);
    display.print( CCS811TVOC );
    display.println( " ppb" );
    // Refresh
    display.refresh();
    delay( 100 );

}
// Display Accelerometer and Gyroscopes
void isDisplayAccGyr() {

    // Text Display Accelerometer and Gyroscopes
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(2);
    display.setTextColor(BLACK);
    // Accelerometer
    display.setCursor(0,5);
    display.println( "Accelero" );
    display.setCursor(0,25);
    display.print( "X: " );
    display.println( imuAX );
    display.setCursor(0,45);
    display.print( "Y: " );
    display.println( imuAY );
    display.setCursor(0,65);
    display.print( "Z: " );
    display.println( imuAZ );
    display.setCursor(0,85);
    display.println( "Gyro" );
    display.setCursor(0,105);
    display.print( "X: " );
    display.println( imuGX );
    display.setCursor(0,125);
    display.print( "Y: " );
    display.println( imuGY );
    display.setCursor(0,145);
    display.print( "Z: " );
    display.println( imuGZ );
    // Refresh
    display.refresh();
    delay( 100 );
      
}
// Display Magnetometer
void isDisplayMag() {

    // Text Display Magnetometer
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(2);
    display.setTextColor(BLACK);
    // Magnetometer
    display.setCursor(0,5);
    display.println( "Magnetometer" );
    display.setCursor(0,25);
    display.print( "X: " );
    display.println( magX );
    display.setCursor(0,45);
    display.print( "Y: " );
    display.println( magY );
    display.setCursor(0,65);
    display.print( "Z: " );
    display.println( magZ );
    // Refresh
    display.refresh();
    delay( 100 );
      
}
// EMF Meter (Single Axis)
void isDisplayEMF() {

    // Text Display EMF Meter
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(2);
    display.setTextColor(BLACK);
    // EMF Meter
    display.setCursor(0,10);
    display.println( "EMF Meter" );
    display.setCursor(0,30);
    display.print( "EMF: " );
    display.println( iEMFDis );
    display.setTextSize(1);
    display.println( "0  1 2 3 4 5 6 7 8 9  10" );
    display.setCursor(0,70);
    display.drawRect(0, 70, iEMFRect , display.height(), BLACK);
    display.fillRect(0, 70, iEMFRect , display.height(), BLACK);
    // Refresh
    display.refresh();
    delay( 100 );

}
// Display Z
void isDisplayZ() {
    // Text Display Z
    // Clear Display
    display.clearDisplay();
    display.setRotation(4);
    display.setTextSize(3);
    display.setTextColor(BLACK);
    // Z
    display.setCursor(0,10);
    display.print( "Z: " );
    display.println( z );
    // Refresh
    display.refresh();
    delay( 100 );
}

getEEPROM.ino

// EEPROM
// isUID EEPROM Unique ID
void isUID()
{
  
  // Is Unit ID
  uid = "";
  for (int x = 0; x < 5; x++)
  {
    uid = uid + char(EEPROM.read(x));
  }
  
}

getEMF.ino

// EMF Meter (Single Axis)
// EMF Meter
void isEMF() {

  isNUMPIXELSoff();

  // Probe EMF Meter
  for (int i = 0; i < NUMREADINGS; i++){

    // Readings
    readings[ i ] = analogRead( iEMF );
    // Average
    averageEMF += readings[i];
    
  }

  // Calculate the average
  val = averageEMF / NUMREADINGS;
  
  // If the reading isn't zero, proceed
  if( val >= 1 ){

    // Turn any reading higher than the senseLimit value into the senseLimit value
    val = constrain( val, 1, senseLimit );
    // Remap the constrained value within a 1 to 1023 range
    val = map( val, 1, senseLimit, 1, 1023 );
    
    // Subtract the last reading
    totalEMF -= readings[ indexEMF ];
    // Read from the sensor
    readings[ indexEMF ] = val;
    // Add the reading to the total
    totalEMF += readings[ indexEMF ];
    // Advance to the next index
    indexEMF = ( indexEMF + 1 );

    // If the average is over 50 ...
    if (averageEMF > 50){

      zz = 0;
      isNUMPIXELS();
      
    }
    
    // If the average is over 250 ...
    if (averageEMF > 250){

      zz = 1;
      isNUMPIXELS();
      
    }

    // If the average is over 350 ...
    if (averageEMF > 350){

      zz = 2;
      isNUMPIXELS();
      
    }

    // If the average is over 500 ...
    if (averageEMF > 500){

      zz = 3;
      isNUMPIXELS();
      
    }

    // If the average is over 650 ...
    if (averageEMF > 650){

      zz = 4;
      isNUMPIXELS();
      
    }

    // If the average is over 750 ...
    if (averageEMF > 750){

      zz = 5;
      isNUMPIXELS();
      
    }

    // If the average is over 850 ...
    if (averageEMF > 850){

      zz = 6;
      isNUMPIXELS();
      
    }

    // If the average is over 950 ...
    if (averageEMF > 950){

      zz = 7;
      isNUMPIXELS();
      
    }

    iEMFDis = averageEMF;
    iEMFRect = map( averageEMF, 1, 1023, 1, 144 );
    
    // Average
    averageEMF = 0;
    
  }
  else
  {

    // Average
    averageEMF = 0;
    
  }
  
}

getGPS.ino

// GPS Receiver
// Setup GPS
void setupGPS() {

  // Setup GPS
  tGPS.begin(  9600 , SERIAL_8N1 , gpsRXPIN , gpsTXPIN );
  
}
// isGPS
void isGPS(){

  // Receives NEMA data from GPS receiver
  // This sketch displays information every time a new sentence is correctly encoded
  while ( tGPS.available() > 0)
    
    if (gps.encode( tGPS.read() ))
    {
     
       // GPS Vector Pointer Target
       displayInfo();
       // GPS Date, Time, Speed, Altitude
       displayDTS();
       
    }
  
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
   
     while(true);
    
  }

}
// GPS Vector Pointer Target
void displayInfo(){

  // Location
  if (gps.location.isValid())
  {
    
     // Latitude
     TargetLat = gps.location.lat();
     // Longitude
     TargetLon = gps.location.lng();
     // GPS Status 2
     GPSSt = "Yes";
    
  }
  else
  {

     // GPS Status 0
     GPSSt = "No";
    
  }

}
// GPS Date, Time, Speed, Altitude
void displayDTS(){

  // Date
  TargetDat = ""; 
  if (gps.date.isValid())
  {
    
     // Date
     // Year
     TargetDat += String(gps.date.year(), DEC);
     TargetDat += "/";
     // Month
     TargetDat += String(gps.date.month(), DEC);
     TargetDat += "/";
     // Day
     TargetDat += String(gps.date.day(), DEC);
    
  }

  // Time
  TargetTim = "";
  if (gps.time.isValid())
  {
    
     // Time
     // Hour
     TargetTim += String(gps.time.hour(), DEC);
     TargetTim += ":";
     // Minute
     TargetTim += String(gps.time.minute(), DEC);
     TargetTim += ":";
     // Secound
     TargetTim += String(gps.time.second(), DEC);
    
  }

  // Speed
  TargetSMS = "";
  TargetSKH = "";
  if (gps.speed.isValid())
  {
    
     // Speed
     // M/S
     int x = gps.speed.mps();
     TargetSMS = String( x, DEC);
     // Km/h
     int y = gps.speed.kmph();
     TargetSKH = String( y, DEC);

  }

  // Altitude
  TargetALT = "";
  if (gps.altitude.isValid())
  {
    
     // Altitude
     // Meters
     int z = gps.altitude.meters();
     TargetALT = String( z, DEC);

  }
  
}

getMagnetometer.ino

// Magnetometer
// Setup Magnetometer
void setupMag() {

  // Setup Magnetometer
  mag.init();
  // Default
  mag.enableDefault();
  
}
// Magnetometer
void isMag() {

  // Magnetometer
  mag.read();
  // Magnetometer x, y, z
  magX = mag.m.x;
  magY = mag.m.y;
  magZ = mag.m.z;
  
}

getNeopix.ino

// NeoPixels
// Neopix
void isNeopix() 
{ 

    // Pixels
    pixels.setBrightness( 150 );
    // Pixels color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor( iNeo, pixels.Color(red,green,blue) ); 
    // This sends the updated pixel color to the hardware
    pixels.show(); 
    // Delay for a period of time (in milliseconds)
    delay(50);     
  
}
// isNUMPIXELS
void isNUMPIXELS()
{

  // Neopix Value
  switch ( zz ) {  
    case 0:
      // NeoPixels
      // Green
      // Red
      red = 0;
      // Green
      green = 255;
      // Blue
      blue = 0;
      // Neopix
      iNeo = 0;      
      isNeopix();
      break;  
    case 1:
      // NeoPixels
      // Green
      // Red
      red = 0;
      // Green
      green = 255;
      // Blue
      blue = 0;
      // Neopix
      iNeo = 1;      
      isNeopix();
      break;
    case 2:
      // NeoPixels
      // Green
      // Red
      red = 0;
      // Green
      green = 255;
      // Blue
      blue = 0;
      // Neopix
      iNeo = 2;      
      isNeopix();
      break;
    case 3:
      // NeoPixels
      // Yellow
      // Red
      red = 255;
      // Green
      green = 255;
      // Blue
      blue = 0;
      // Neopix
      iNeo = 3;      
      isNeopix();
      break;
    case 4:
      // NeoPixels
      // Yellow
      // Red
      red = 255;
      // Green
      green = 255;
      // Blue
      blue = 0;
      // Neopix
      iNeo = 4;      
      isNeopix();
      break;
    case 5:
      // NeoPixels
      // Yellow
      // Red
      red = 255;
      // Green
      green = 255;
      // Blue
      blue = 0;
      // Neopix
      iNeo = 5;      
      isNeopix();
      break;
    case 6:
      // NeoPixels
      // Yellow
      // Red
      red = 255;
      // Green
      green = 255;
      // Blue
      blue = 0;
      // Neopix
      iNeo = 6;      
      isNeopix();    
      break;
    case 7:
      // NeoPixels
      // Red
      // Red
      red = 255;
      // Green
      green = 0;
      // Blue
      blue = 0;
      // Neopix
      iNeo = 7;      
      isNeopix();     
      break;
  }
  
}
// isNUMPIXELSoff
void isNUMPIXELSoff()
{

   // Black Off
   // NeoPixels
   for(int y=0; y < NUMPIXELS; y++)
   { 
      red = 0;                                 // Red
      green = 0;                               // Green
      blue = 0;                                // Blue
      iNeo = y;                                // Neopix  
      isNeopix();    
   }
   
}

getRTC.ino

// Date & Time
// PCF8523 Precision RTC
void setupRTC() {

  // Date & Time
  // pcf8523 Precision RTC   
  if (! rtc.begin()) {
    while (1);
  }  
  
  if (! rtc.initialized()) {
    
    // Following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
    // rtc.adjust(DateTime(2021, 8, 18, 8, 48, 0));
    
  }
  
}
// Date and Time RTC PCF8523
void isRTC () {

  // Date and Time
  dateRTC = "";
  timeRTC = "";
  DateTime now = rtc.now();
  
  // Date
  // Year
  dateRTC = now.year(), DEC; 
  dateRTC = dateRTC + "/";
  // Month
  dateRTC = dateRTC + now.month(), DEC;
  dateRTC = dateRTC + "/";
  // Day
  dateRTC = dateRTC + now.day(), DEC;
  
  // Time
  // Hour
  timeRTC = now.hour(), DEC;
  timeRTC = timeRTC + ":";
  // Minute
  timeRTC = timeRTC + now.minute(), DEC;
  timeRTC = timeRTC + ":";
  // Second
  timeRTC = timeRTC + now.second(), DEC;
  
}

getRot.ino

// Rotary Switch
// isRot - iRotVal - Value
void isRot() {
  
  // Rotary Switch
  z = analogRead( iRotNum );
  
  // Rotary Switch - 10 Position
  // Number 1 => 10
  if ( z >= 3600 ) {

    // Z
    iRotVal = 10;
    
  } else if ( z >= 3200 ) {

    // Z
    iRotVal = 9;
    
  } else if ( z >= 2700 ) {

    // Z
    iRotVal = 8;
    
  } else if ( z >= 2400 ) {

    // Z
    iRotVal = 7;
    
  } else if ( z >= 2000 ) {

    // Z
    iRotVal = 6;
    
  } else if ( z >= 1600 ) {

    // Z
    iRotVal = 5;
    
  } else if ( z >= 1200 ) {

    // Z
    iRotVal = 4;
    
  } else if ( z >= 900 ) {

    // Z
    iRotVal = 3;
    
  } else if ( z >= 500 ) {

    // Z
    iRotVal = 2;
    
  } else {

    // Z
    iRotVal = 1;
    
  }

  // Range Value
  switch ( iRotVal ) {
    case 1:

      // Display Date, Time
      isDisplayDate();
       
      break;
    case 2:

      // Display GPS
      isDisplayGPS();
         
      break;
    case 3:

      // GPS Date, Time, Speed, Altitude
      //isDisplayGPSDate();
      
      break;  
    case 4:
      
      // GPS Display Date, Time, Speed
      isDisplayGPSDate();
      
      break;
    case 5:
      
      // Display SparkFun BME280 - Temperature, Humidity, Altitude and Barometric Pressure
      isDisplayBME280();
      
      break;
    case 6:
      
      // Display CCS811 - eCO2 & tVOC
      isDisplayCCS811();
      
      break;       
    case 7:

      // Accelerometer and Gyroscopes
      isDisplayAccGyr();
      
      break; 
    case 8:
         
      // Display Magnetometer
      isDisplayMag();
      
      break; 
    case 9:
      
      // EMF Meter (Single Axis)
      isDisplayEMF();
      
      break;
    case 10:

      // Display UID
      isDisplayUID();
      
      break;
  }
  
}

getSD.ino

// MicroSD Card
// MicroSD Setup
void setupSD() {

    // MicroSD Card
    pinMode( chipSelect , OUTPUT );
    if(!SD.begin( chipSelect )){
        ;  
        return;
    }
    
    uint8_t cardType = SD.cardType();

    // CARD NONE
    if(cardType == CARD_NONE){
        ; 
        return;
    }

    // SD Card Type
    if(cardType == CARD_MMC){
        ; 
    } else if(cardType == CARD_SD){
        ; 
    } else if(cardType == CARD_SDHC){
        ; 
    } else {
        ; 
    } 

    // Size
    uint64_t cardSize = SD.cardSize() / (1024 * 1024);
 
}
// MicroSD Card
void isSD() {

  zzzzzz = "";

  // EEPROM Unique ID|Version|Date|Time|GPS Status|Target Latitude|Target Longitude|GPS Date|GPS Time|GPS Speed M/S|GPS Speed Km/h|GPS Altitude
  //|Temperature Celsius|Humidity|Altitude Meters|Barometric Pressure|eCO2 Concentration|tVOC Concentration|Accelerometer X|Accelerometer Y|Accelerometer Z|
  //Gyroscopes X|Gyroscopes Y|Gyroscopes Z|Magnetometer X|Magnetometer Y|Magnetometer Z|EMF|\r
  zzzzzz = uid + "|" + sver + "|" + dateRTC + "|" + timeRTC + "|" + GPSSt + "|" + TargetLat + "|" + TargetLon + "|" + TargetDat + "|" + TargetTim + "|" + 
  TargetSMS + "|" + TargetSKH + "|" + TargetALT  + "|" + BMEtempC + "|" + BMEhumid + "|" + BMEaltitudeM + "|" + BMEpressure + "|" + CCS811CO2 + "|" 
  + CCS811TVOC + "|" + imuAX + "|" + imuAY + "|" + imuAZ + "|" + imuGX + "|" + imuGY + "|" + imuGZ + "|" + magX + "|" + magY + "|" + magZ + "|" + iEMFDis + "|\r";

  // msg + 1
  char msg[zzzzzz.length() + 1];

  zzzzzz.toCharArray(msg, zzzzzz.length() + 1);

  // Append File
  appendFile(SD, "/espdata.txt", msg );
  
}
// List Dir
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    
    // List Dir
    dirname;
    
    File root = fs.open(dirname);
    
    if(!root){
        return;
    }
    
    if(!root.isDirectory()){
        return;
    }

    File file = root.openNextFile();
    
    while(file){
        if(file.isDirectory()){
            file.name();
            if(levels){
                listDir(fs, file.name(), levels -1);
            }
        } else {
            file.name();
            file.size();
        }
        file = root.openNextFile();
    }
    
}
// Write File
void writeFile(fs::FS &fs, const char * path, const char * message){
    
    // Write File
    path;
    
    File file = fs.open(path, FILE_WRITE);
    
    if(!file){
        return;
    }
    
    if(file.print(message)){
        ;  
    } else {
        ;  
    }
    
    file.close();
    
}
// Append File
void appendFile(fs::FS &fs, const char * path, const char * message){
    
    // Append File
    path;
    
    File file = fs.open(path, FILE_APPEND);
    
    if(!file){
        return;
    }
    
    if(file.print(message)){
        ;  
    } else {
        ;  
    }
    
    file.close();
    
}

setup.ino

// Setup
void setup()
{
  
  // EEPROM Size
  EEPROM.begin(EEPROM_SIZE);
  
  // EEPROM Unique ID
  isUID();
  
  // NeoPixels
  // This initializes the NeoPixel library
  pixels.begin();
  
  // GPS Receiver
  // Setup GPS
  setupGPS();

  // Set up I2C bus
  Wire.begin();

  // SparkFun BME280 - Temperature, Humidity, Altitude and Barometric Pressure
  myBME280.begin();
  
  // CCS811 - eCO2 & tVOC
  myCCS811.begin();
  
  // SHARP Display Start & Clear the Display
  display.begin();
  // Clear Display
  display.clearDisplay();

  // Date & Time RTC
  // PCF8523 Precision RTC
  isDisplayUID();
  
  // Setup RTC
  setupRTC();

  //MicroSD Card
  setupSD();

  // Setup IMU
  setupIMU();

  // Setup Magnetometer
  setupMag();

  // NeoPixels
  // isNUMPIXELS Off
  isNUMPIXELSoff();

  // Initialize the LED Green
  pinMode(iLEDGreen, OUTPUT);

  // Slide Switch
  pinMode(iSS1, INPUT);

  delay( 5000 );
  
}

——

People can contact us: https://www.donluc.com/?page_id=1927

Technology Experience

  • Single-Board Microcontrollers (PIC, Arduino, Raspberry Pi,Espressif, etc…)
  • IoT
  • Robotics
  • Research & Development (R & D)
  • Desktop Applications (Windows, OSX, Linux, Multi-OS, Multi-Tier, etc…)
  • Mobile Applications (Android, iOS, Blackberry, Windows Mobile, Windows CE, etc…)
  • Web Applications (LAMP, Scripting, Java, ASP, ASP.NET, RoR, Wakanda, etc…)
  • Social Media Programming & Integration (Facebook, Twitter, YouTube, Pinterest, etc…)
  • Content Management Systems (WordPress, Drupal, Joomla, Moodle, etc…)
  • Bulletin Boards (phpBB, SMF, Vanilla, jobberBase, etc…)
  • eCommerce (WooCommerce, OSCommerce, ZenCart, PayPal Shopping Cart, etc…)

Instructor

  • PIC Microcontrollers
  • Arduino
  • Raspberry Pi
  • Espressif
  • Robotics
  • DOS, Windows, OSX, Linux, iOS, Android, Multi-OS
  • Linux-Apache-PHP-MySQL

Follow Us

J. Luc Paquin – Curriculum Vitae – 2021 English & Español
https://www.jlpconsultants.com/CV/LucPaquinCVEngMk2021c.pdf
https://www.jlpconsultants.com/CV/LucPaquinCVEspMk2021c.pdf

Web: https://www.donluc.com/
Web: https://www.jlpconsultants.com/
Web: https://www.donluc.com/DLE/
Web: https://www.donluc.com/DLHackster/
Web: https://www.hackster.io/neosteam-labs
Web: https://zoom.us/
Patreon: https://www.patreon.com/DonLucElectronics
Facebook: https://www.facebook.com/neosteam.labs.9/
YouTube: https://www.youtube.com/channel/UC5eRjrGn1CqkkGfZy0jxEdA
Twitter: https://twitter.com/labs_steam
Pinterest: https://www.pinterest.com/NeoSteamLabs/
Instagram: https://www.instagram.com/neosteamlabs/

Don Luc

#17 – Meditation – Glasses LED Meditation – NeoPixel Stick – Mk06

——

#donluc #meditation #glassesledmeditation #musicshield #neopixels #arduino #sparkfun #project #programming #electronics #microcontrollers #consultant #zoom #patreon #videoblog

——

NeoPixel Stick

——

NeoPixel Stick

——

NeoPixel Stick

——

NeoPixel Stick – 8 x 5050 RGB LED with Integrated Drivers

Make your own little LED strip arrangement with this stick of NeoPixel LEDs. We crammed 8 of the tiny 5050 (5mm x 5mm) smart RGB LEDs onto a PCB with mounting holes and a chainable design. Use only one microcontroller pin to control as many as you can chain together! Each LED is addressable as the driver chip is inside the LED. Each one has ~18mA constant current drive so the color will be very consistent even if the voltage varies, and no external choke resistors are required making the design slim. Power the whole thing with 5VDC (4-7V works).

The LEDs are ‘chainable’ by connecting the output of one stick into the input of another. There is a single data line with a very timing-specific protocol. Since the protocol is very sensitive to timing, it requires a real-time microconroller such as an AVR, Arduino, PIC, mbed, etc. It cannot be used with a Linux-based microcomputer or interpreted microcontroller such as the netduino or Basic Stamp. Our wonderfully-written Neopixel library for Arduino supports these pixels. As it requires hand-tuned assembly it is only for AVR cores but others may have ported this chip driver code so please google around. An 8MHz or faster processor is required.

DL2103Mk02

1 x Arduino Uno – R3
1 x ProtoScrewShield
1 x Music Shield V1.1
1 x NeoPixel Stick – 8 x 5050 RGB LED with Integrated Drivers
1 x microSD Card – 2GB
1 x Panel Mount 1K potentiometer
2 x Knob
1 x SparkFun Rotary Switch – 10 Position
1 x SparkFun Rotary Switch Breakout
1 x Breadboard Solderable
11 x 1K Ohm
1 x Hamburger Mini Speaker
17 x Wire Solid Core – 22 AWG
1 x Ethernet Cable Cat 5 – 2 Metres
1 x Half-Size Breadboard
1 x SparkFun Cerberus USB Cable

Arduino Uno – R3

RW0 – Analog A4
PO0 – Analog A5
NP1 – Digital 1
MB0 – RST
VIN – +5V
GND – GND

DL2103Mk02p.ino

// ***** Don Luc Electronics © *****
// Software Version Information
// #17 - Meditation - Glasses LED Meditation - NeoPixel Stick - Mk06
// 03-02
// DL2103Mk02p.ino 17-06
// DL2103Mk02
// 1 x Arduino Uno - R3
// 1 x ProtoScrewShield
// 1 x Music Shield V1.1
// 1 x NeoPixel Stick - 8 x 5050 RGB LED with Integrated Drivers
// 1 x microSD Card - 2GB
// 1 x Panel Mount 1K potentiometer
// 11 x Knob
// 1 x SparkFun Rotary Switch - 10 Position
// 1 x SparkFun Rotary Switch Breakout
// 1 x Breadboard Solderable
// 11 x 1K Ohm
// 1 x Hamburger Mini Speaker
// 17 x Wire Solid Core - 22 AWG
// 1 x Ethernet Cable Cat 5 - 2 Metres
// 1 x Half-Size Breadboard
// 1 x SparkFun Cerberus USB Cable

// Include the Library Code
// NeoPixel
#include <Adafruit_NeoPixel.h>
// Fat 16
#include <Fat16.h>
#include <Fat16Util.h>
// New SPI
#include <NewSPI.h>
// Arduino
#include <arduino.h>
// Music Player
#include "pins_config.h"
#include "vs10xx.h"
#include "newSDLib.h"
#include "MusicPlayer.h"

// NeoPixels
#define PIN 1
// How many NeoPixels are attached to the Arduino
#define NUMPIXELS 8
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
// Color
// Red
int red = 0;
// Green
int green = 0;
// Blue
int blue = 0;
// Panel Mount 1K potentiometer
// Brighten
int BrightenValue = 0;
// Color
const int iSensorColor = A5;
int y = 0;
int ColorVal = 0;

// Rotary Switch - 10 Position
// Number 1 => 10
int iRotNum = A4;
// iRotVal - Value 
int iRotVal = 0;
// Number
int z = 0;
int x = 0;

// Music Player
MusicPlayer myplayer;

// Software Version Information
String sver = "17-06";

void loop() {

  // Rotary Switch
  isRot();

}

getNeopix.ino

// Neopix
void isNeopix() {
  
  for(int i=0; i<NUMPIXELS; i++){

    // Neopix
    // BrightenValue = 40
    BrightenValue = 40;
    pixels.setBrightness( BrightenValue );

    // The pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(red,green,blue));
    
    // This sends the updated pixel color to the hardware
    pixels.show();
 
  }
  
}
// Range Color
void isRangeColor() {

  // Range Color
  ColorVal = analogRead( iSensorColor );
  y = (ColorVal / 127);
  
  switch ( y ) {
    case  0:
      // Blue
      red = 0;
      green = 102;
      blue = 204;        
      isNeopix();
      break;
    case 1:
      // Yellow
      red = 255;
      green = 255;
      blue = 0;        
      isNeopix();
      break;
    case 2:
      // Pink
      red = 255;
      green = 153;
      blue = 203;        
      isNeopix();
      break;
    case 3:
      // White
      red = 255;
      green = 255;
      blue = 255;        
      isNeopix();
      break;  
    case 4:
      // Green
      red = 0;
      green = 255;
      blue = 0;        
      isNeopix();
      break;
    case 5:
      // Orange
      red = 255;
      green = 102;
      blue = 0;        
      isNeopix();
      break;
    case 6:
      // Violet
      red = 204;
      green = 102;
      blue = 204;        
      isNeopix();
      break;     
    case 7:
      // Red
      red = 255;
      green = 0;
      blue = 0;        
      isNeopix();
      break; 
  }
  
}

getRot.ino

// Rotary Switch
// isRot - iRotVal - Value
void isRot() {

  // Rotary Switch
  z = analogRead( iRotNum );
  x = map(z, 0, 4095, 0, 9);
  iRotVal = map(z, 0, 1023, 0, 10);

  // Range Value
  switch ( iRotVal ) {
    case 0:

      // Range Color
      isRangeColor();
      
      break;
    case 1:

      // Music
      // Add To Playlist
      // 3:18
      myplayer.addToPlaylist("DLEMk001.mp3");
      // 2:47
      myplayer.addToPlaylist("DLEMk002.mp3");
      // 4.34
      myplayer.addToPlaylist("DLEMk003.mp3");
      // There are two songs in the playlist
      // 10:37
      myplayer.playList();
      while(1);
      
      break;
    case 2:

      // Music
      // Add To Playlist
      // 22:53
      myplayer.addToPlaylist("DLEMk004.mp3");
      // There are two songs in the playlist
      // 22:53
      myplayer.playList();
      while(1);
      
      break;  
    case 3:

      // Music
      // Add To Playlist
      // 4:18
      myplayer.addToPlaylist("DLEMk005.mp3");
      // 4:20
      myplayer.addToPlaylist("DLEMk006.mp3");
      // There are two songs in the playlist
      // 8:38
      myplayer.playList();
      while(1);
      
      break;
    case 4:

      // Music
      // Add To Playlist
      // 9:14
      myplayer.addToPlaylist("DLEMk007.mp3");
      // 7:52
      myplayer.addToPlaylist("DLEMk008.mp3");
      // There are two songs in the playlist
      // 17:07
      myplayer.playList();
      while(1);
      
      break;
    case 5:

      // Music
      // Add To Playlist
      // 4:37
      myplayer.addToPlaylist("DLEMk009.mp3");
      // There are two songs in the playlist
      // 4:37
      myplayer.playList();
      while(1);
      
      break;       
    case 6:

      // Music
      // Add To Playlist
      // 8:40
      myplayer.addToPlaylist("DLEMk010.mp3");
      // 8:40
      myplayer.playList();
      while(1); 
      
      break; 
    case 7:
         
      // Music
      // Add To Playlist
      // 1:31
      myplayer.addToPlaylist("DLEMk011.mp3");
      // 3:29
      myplayer.addToPlaylist("DLEMk012.mp3");
      // There are two songs in the playlist
      // 5:00
      myplayer.playList();
      while(1);
      
      break; 
    case 8:

      // Music
      // Add To Playlist
      // 6:14
      myplayer.addToPlaylist("DLEMk013.mp3");
      // 5:17
      myplayer.addToPlaylist("DLEMk014.mp3");
      // There are two songs in the playlist
      // 11:31
      myplayer.playList();
      while(1); 
      
      break;
    case 9:

      // Music
      // Add To Playlist
      // 6:30
      myplayer.addToPlaylist("DLEMk015.mp3");
      // 3:00
      myplayer.addToPlaylist("DLEMk016.mp3");
      // There are two songs in the playlist
      // 9:30
      myplayer.playList();
      while(1); 
      
      break;
  }

}

setup.ino

// Setup
void setup() {
  
   // This initializes the NeoPixel library
   pixels.begin();
   delay(50);

   // Range Color
   isRangeColor();

   // Music Player
   // Will initialize the hardware and set default mode to be normal
   myplayer.begin();

}

Music 01 – 10m 37s

DLEMk001.mp3
DLEMk002.mp3
DLEMk003.mp3

Music 02 – 22m 53s

DLEMk004.mp3

Music 03 – 8m 38s

DLEMk005.mp3
DLEMk006.mp3

Music 04 – 17m 07s

DLEMk007.mp3
DLEMk008.mp3

Music 05 – 4m 37s

DLEMk009.mp3

Music 06 – 8m 40s

DLEMk010.mp3

Music 07 – 5m 00s

DLEMk011.mp3
DLEMk012.mp3

Music 08 – 11m 31s

DLEMk013.mp3
DLEMk014.mp3

Music 09 – 9m 30s

DLEMk015.mp3
DLEMk016.mp3

People can contact us: https://www.donluc.com/?page_id=1927

Technology Experience

  • Single-Board Microcontrollers (PIC, Arduino, Raspberry Pi,Espressif, etc…)
  • Robotics
  • Research & Development (R & D)
  • Desktop Applications (Windows, OSX, Linux, Multi-OS, Multi-Tier, etc…)
  • Mobile Applications (Android, iOS, Blackberry, Windows Mobile, Windows CE, etc…)
  • Web Applications (LAMP, Scripting, Java, ASP, ASP.NET, RoR, Wakanda, etc…)
  • Social Media Programming & Integration (Facebook, Twitter, YouTube, Pinterest, etc…)
  • Content Management Systems (WordPress, Drupal, Joomla, Moodle, etc…)
  • Bulletin Boards (phpBB, SMF, Vanilla, jobberBase, etc…)
  • eCommerce (WooCommerce, OSCommerce, ZenCart, PayPal Shopping Cart, etc…)

Instructor

  • PIC Microcontrollers
  • Arduino
  • Raspberry Pi
  • Espressif
  • Robotics
  • DOS, Windows, OSX, Linux, iOS, Android, Multi-OS
  • Linux-Apache-PHP-MySQL

Follow Us

J. Luc Paquin – Curriculum Vitae
https://www.donluc.com/DLE/LucPaquinCVEngMk2021a.pdf

Web: https://www.donluc.com/
Web: http://www.jlpconsultants.com/
Web: https://www.donluc.com/DLE/
Web: https://www.donluc.com/DLHackster/
Web: https://www.hackster.io/neosteam-labs
Web: https://zoom.us/
Patreon: https://www.patreon.com/DonLucElectronics
Facebook: https://www.facebook.com/neosteam.labs.9/
YouTube: https://www.youtube.com/channel/UC5eRjrGn1CqkkGfZy0jxEdA
Twitter: https://twitter.com/labs_steam
Pinterest: https://www.pinterest.com/NeoSteamLabs/
Instagram: https://www.instagram.com/neosteamlabs/

Don Luc

Categories
Archives