Thursday, March 30, 2017

Group 1 - OLED Display (Blog 1)


Our end goals with this project are to be able to:

Provide power to the OLED via the Flora/Breadboard
Create our own unique welcome/splash screen
Create unique custom content on the display (by uploading a bitmap)
So far, we have accomplished the first goal, that was the process of our first class on this.  We successfully wired everything up (as seen in attached images), and ran some sample code into the OLED from its library, in order to create some cycling test imagery.


Using the I2C program and library, we used this sample code:

This example is for a 128x64 size display using I2C to communicate
3 pins are required to interface (2 I2C and one reset)

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 12
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2


#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };

//#if (SSD1306_LCDHEIGHT != 64)
//#error("Height incorrect, please fix Adafruit_SSD1306.h!");
//#endif

void setup() {
Serial.begin(9600);

// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // initialize with the I2C addr 0x3D (for the 128x64)
// init done

// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.display();
delay(2000);

// Clear the buffer.
display.clearDisplay();

// draw a single pixel
display.drawPixel(10, 10, WHITE);
// Show the display buffer on the hardware.
// NOTE: You _must_ call display after making any drawing commands
// to make them visible on the display hardware!
display.display();
delay(2000);
display.clearDisplay();

// draw many lines
testdrawline();
display.display();
delay(2000);
display.clearDisplay();

// draw rectangles
testdrawrect();
display.display();
delay(2000);
display.clearDisplay();

// draw multiple rectangles
testfillrect();
display.display();
delay(2000);
display.clearDisplay();

// draw mulitple circles
testdrawcircle();
display.display();
delay(2000);
display.clearDisplay();

// draw a white circle, 10 pixel radius
display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
display.display();
delay(2000);
display.clearDisplay();

testdrawroundrect();
delay(2000);
display.clearDisplay();

testfillroundrect();
delay(2000);
display.clearDisplay();

testdrawtriangle();
delay(2000);
display.clearDisplay();

testfilltriangle();
delay(2000);
display.clearDisplay();

// draw the first ~12 characters in the font
testdrawchar();
display.display();
delay(2000);
display.clearDisplay();

// draw scrolling text
testscrolltext();
delay(2000);
display.clearDisplay();

// text display tests
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Hello, world!");
display.setTextColor(BLACK, WHITE); // 'inverted' text
display.println(3.141592);
display.setTextSize(2);
display.setTextColor(WHITE);
display.print("0x"); display.println(0xDEADBEEF, HEX);
display.display();
delay(2000);
display.clearDisplay();

// miniature bitmap display
display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
display.display();
delay(1);

// invert the display
display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(1000);
display.clearDisplay();

// draw a bitmap icon and 'animate' movement
testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
}


void loop() {

}


void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
uint8_t icons[NUMFLAKES][3];

// initialize
for (uint8_t f=0; f< NUMFLAKES; f++) {
icons[f][XPOS] = random(display.width());
icons[f][YPOS] = 0;
icons[f][DELTAY] = random(5) + 1;

Serial.print("x: ");
Serial.print(icons[f][XPOS], DEC);
Serial.print(" y: ");
Serial.print(icons[f][YPOS], DEC);
Serial.print(" dy: ");
Serial.println(icons[f][DELTAY], DEC);
}

while (1) {
// draw each icon
for (uint8_t f=0; f< NUMFLAKES; f++) {
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
}
display.display();
delay(200);

// then erase it + move it
for (uint8_t f=0; f< NUMFLAKES; f++) {
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
// move it
icons[f][YPOS] += icons[f][DELTAY];
// if its gone, reinit
if (icons[f][YPOS] > display.height()) {
icons[f][XPOS] = random(display.width());
icons[f][YPOS] = 0;
icons[f][DELTAY] = random(5) + 1;
}
}
}
}


void testdrawchar(void) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);

for (uint8_t i=0; i < 168; i++) {
if (i == '\n') continue;
display.write(i);
if ((i > 0) && (i % 21 == 0))
display.println();
}
display.display();
delay(1);
}

void testdrawcircle(void) {
for (int16_t i=0; i<display.height(); i+=2) {
display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
display.display();
delay(1);
}
}

void testfillrect(void) {
uint8_t color = 1;
for (int16_t i=0; i<display.height()/2; i+=3) {
// alternate colors
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
display.display();
delay(1);
color++;
}
}

void testdrawtriangle(void) {
for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) {
display.drawTriangle(display.width()/2, display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, WHITE);
display.display();
delay(1);
}
}

void testfilltriangle(void) {
uint8_t color = WHITE;
for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
display.fillTriangle(display.width()/2, display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, WHITE);
if (color == WHITE) color = BLACK;
else color = WHITE;
display.display();
delay(1);
}
}

void testdrawroundrect(void) {
for (int16_t i=0; i<display.height()/2-2; i+=2) {
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, WHITE);
display.display();
delay(1);
}
}

void testfillroundrect(void) {
uint8_t color = WHITE;
for (int16_t i=0; i<display.height()/2-2; i+=2) {
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
if (color == WHITE) color = BLACK;
else color = WHITE;
display.display();
delay(1);
}
}

void testdrawrect(void) {
for (int16_t i=0; i<display.height()/2; i+=2) {
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
display.display();
delay(1);
}
}

void testdrawline() {
for (int16_t i=0; i<display.width(); i+=4) {
display.drawLine(0, 0, i, display.height()-1, WHITE);
display.display();
delay(1);
}
for (int16_t i=0; i<display.height(); i+=4) {
display.drawLine(0, 0, display.width()-1, i, WHITE);
display.display();
delay(1);
}
delay(250);

display.clearDisplay();
for (int16_t i=0; i<display.width(); i+=4) {
display.drawLine(0, display.height()-1, i, 0, WHITE);
display.display();
delay(1);
}
for (int16_t i=display.height()-1; i>=0; i-=4) {
display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
display.display();
delay(1);
}
delay(250);

display.clearDisplay();
for (int16_t i=display.width()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
display.display();
delay(1);
}
for (int16_t i=display.height()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
display.display();
delay(1);
}
delay(250);

display.clearDisplay();
for (int16_t i=0; i<display.height(); i+=4) {
display.drawLine(display.width()-1, 0, 0, i, WHITE);
display.display();
delay(1);
}
for (int16_t i=0; i<display.width(); i+=4) {
display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE);
display.display();
delay(1);
}
delay(250);
}

void testscrolltext(void) {
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(10,0);
display.clearDisplay();
display.println("scroll");
display.display();
delay(1);

display.startscrollright(0x00, 0x0F);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x0F);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrolldiagright(0x00, 0x07);
delay(2000);
display.startscrolldiagleft(0x00, 0x07);
delay(2000);
display.stopscroll();
}
Chat Conversation End



Group 4 - Bluart Day 2

In this lab class, we realized that the main problem we had in the previous class was not using the the adafruit micro board, and that was the reason the code was not uploading correctly. After that we were able to connect the UART device to the android phone using the arduino connect application. We were able to send and receive messages between the app and the serial monitor in arduino. Now we are trying to manipulate the code so that we can use the bluetooth connection to do more complex commands, like turning on a motor. For the rest of the class we tried to edit the code so that we can do more complex commands, however we couldn’t figure out a way to make it do so. 

Group 2_GPS_3/30/17

We started exactly from where we left of last session, the GPS module set up and connected with the Flora board and then back to the computer, running off of a switch. Our code right now, seems to be operating properly, but we're getting strings of random characters, rather than a latitude and longitude. For today, we will be working on converting this to an actual position, potentially having to go outside for this to work, as Adafruit states that their GPS module will only work outdoors.


So we took the computer and hardware outside, and sure enough it was able to pinpoint our location, after a minute or so of random characters being printed, the red light on the GPS module went solid and a location, and even other information was printed out to us.



The location is stated as 4300.0302N and 7846.9946W, but its obvious that this is translated as 43N 78.5W, which is completely accurate.

Once we came back inside, we updated the code to write to EEPROM rather than just the terminal. The code we are writing would save the first four characters of the latitude and longitude only, not any of the other information, as this would be a waste of space and non essential. We wrote a bit of test code, to dry run this idea, having the serial monitor write back the first for letters of messages that we saved. After this, being sure that we were able to write to EEPROM, we wrote a final bit of code.

#include <Adafruit_GPS.h>

#include <EEPROM.h>

int addr = 0;
const int inPin = 6;     // the number of the pushbutton pin
const int ledPin =  7;      // the number of the LED pin
int buttonState = 0; // variable for reading the pushbutton status

// what's the name of the hardware serial port?
#define GPSSerial Serial1
// Connect to the GPS on the hardware port
Adafruit_GPS GPS(&GPSSerial);
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO false

uint32_t timer = millis();


void setup() {
  // put your setup code here, to run once:
  // initialize the pushbutton pin as an input:
  pinMode(inPin, INPUT);
  pinMode(ledPin, OUTPUT);
  //while (!Serial);  // uncomment to have the sketch wait until Serial is ready
  
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
     
  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz
     
  // Request updates on antenna status, comment out to keep quiet
  GPS.sendCommand(PGCMD_ANTENNA);

  delay(1000);
  
  // Ask for firmware version
  GPSSerial.println(PMTK_Q_RELEASE);

  clearEeprom();
  
}

void loop() {
  // put your main code here, to run repeatedly:
  buttonState = digitalRead(inPin);
  if (buttonState == HIGH) {
    //GPSSerial.begin(9600);
    digitalWrite(ledPin, HIGH);
    // read data from the GPS in the 'main loop'
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
  if (GPSECHO)
    if (c) Serial.print(c);
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences!
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
    Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
    if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
      return; // we can fail to parse a sentence in which case we should just wait for another
    }
    // if millis() or timer wraps around, we'll just reset it
    if (timer > millis()) timer = millis();
     
    // approximately every 2 seconds or so, print out the current stats
    if (millis() - timer > 2000) {
      timer = millis(); // reset the timer
      if (GPS.fix) {
        Serial.print("Location: ");
        Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
        Serial.print(", ");
        Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);

        // Save location to eeprom in the format
        // lat,lon\n
        // ie. 43000.0302N,78468.9946W\n
        // writen as ints (ASCII value)
        //23 spaces taken per addr saved
        //1024 space total
        // about 44 addresses able to be logged

        writeToEeprom((String)GPS.latitude);
        EEPROM.write(addr, ".");
        addr = addr + 1;
        delay(1);

        writeToEeprom((String)GPS.lat);
        EEPROM.write(addr, ",");
        addr = addr + 1;
        delay(1);

        writeToEeprom((String)GPS.longitude);
        EEPROM.write(addr, ".");
        addr = addr + 1;
        delay(1);

        writeToEeprom((String)GPS.lon);
        EEPROM.write(addr, ",");
        addr = addr + 1;
        delay(1);
        
        // write endline char
        EEPROM.write(addr, "\n");
        addr = addr + 1;
        delay(1);
      
      }
    }
  }
  else {
    digitalWrite(ledPin, LOW);
    //GPSSerial.begin(9600);
  }

}

// function to clear memory
int clearEeprom(){
  for(int i = 0; i< 1024; i++){
    EEPROM.write(i,"");
  }
  return 0;
}

// writes first 4 chars byte by byte
int writeToEeprom(String data){
  for(int i = 0; i < 5; i++){
        EEPROM.write(addr, (int)data[i]);

        addr = addr + 1;
        if (addr == EEPROM.length()) {
          addr = 0; // resets addr counter
          break;
        }
        
      }
      return 0;
  
}

With the updated code running and working properly when outside, we got a smaller, thinner and lighter breadboard (right side), which we soldered all of the hardware to. 





In order to create a more permanent and mobile setup, we will eventually forgo alligator clips in general as those are not very secure when mobile. After this, we are going to look into make everything battery powered, rather than by the computer, and will it writing to EEPROM, we will be able to go fully mobile. The EEPROM has space for around 50 locations to be saved to. 

Ideally, the switch would be turned on, the GPS module would blink red until it gathers our location data, go solid red and then save the location, at which point we can switch it off again. This data would be logged to EEPROM.

We will be testing our model during our next session.



Group 4 - Bluetooth Low Energy UART

Manu Roy, Devin Dejoode, Russell Potter 

We started off the class getting to know each other, and trying to understand what the group project wanted us to do. We were assigned the Bluetooth Low Energy UART group project, and after looking online we found the android API from adafruit, and downloaded it onto our phone. The app reads bluetooth connections available in the area, and now we are working towards connecting the phone to the bluefruit LE UART friend device. After looking at some forums online, we are thinking of creating a connection where we can send messages to and from a computer and the device. We downloaded the adafruit_bluefruitLE_nRF51 custom library, and loaded it into the arduino program. Now we are trying different connection methods from the bluetooth device, to the flora, to the computer, just to make sure the device itself works. We were finally able to make the correct connections to get the LED on the bluetooth device to turn on. Now we are looking through the online resources of adafruit to connect the UART to the flora. We followed the instructions on one of the adafruit pages and commented some of the code used out, and the we were able to get a connection from the computer to the bluefruit LE UART. We were then able to connect the phone to the UART using the application we downloaded. ​

Tuesday, March 28, 2017

Group 2_GPS_3/28/17

So our end goal is to create a code that will utilize the Flora and the Flora Wearable Ultimate GPS Module, to log and store positioning data when turned on and off.
Thinking through this, the first thing that we wanted to do was create a simple bit of code that would recognize that there was a switch and do something when turned on and off. In order to write the code for this, we pulled bits of code from labs 3 and 6:
#include <EEPROM.h>
const int inPin = 6;     // the number of the pushbutton pin
const int ledPin =  7;      // the number of the LED pin
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
  // put your setup code here, to run once:
  // initialize the pushbutton pin as an input:
  pinMode(inPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  buttonState = digitalRead(inPin);
  if (buttonState == HIGH) {
    digitalWrite(ledPin, HIGH);  
  }
  else {
    digitalWrite(ledPin, LOW);
  }

}

This bit of code recognizes the switch and turns on and off the red LED on the Flora board.
We wired the switch using a breadboard connecting the Flora to the breadboard. We went 3.3V to positive terminal on the breadboard, GND to negative terminal. Pin #6, negative terminal, and one end of a resistor to the switch. The other end of the resistor was wired to the positive terminal. Pictures attached.
The next step was to set up the actual hardware, which was rather simple, we actually found a very useful tutorial pdf online at https://cdn-learn.adafruit.com/downloads/pdf/flora-wearable-gps.pdf, which helped us learn how to hook up the flora to the GPS. 
We hooked up the Flora to the GPS as such: alligator clips to connect Flora's 3.3V pad to the 3.3V pad on the GPS. Likewise connect RX to TX and TX to RX, then finally GND to GND. The Flora board got plugged directly into the laptop that was running Arduino.
Once we had the hardware set up, we modified the code to include the GPS, this we found in an Adafruit tutorial and had to include certain libraries, full code below. We set up the code so that when the switch is turned on or off, a light on the Flora board also turns on and off, such that we can tell it is actually working. We got to a point with this code and set up in which in the serial monitor, the GPS was spitting out strings of numbers to us, not yet coordinates. From here, we have to convert this string of random characters to an actual latitude and longitude coordinate system. 
It does seem like we will have to be outside for the GPS to work however, as Adafruit themselves says that this is required. This will be next class, as well as working on making this battery powered and logging to something other than a computer, so we can go mobile.

#include <Adafruit_GPS.h>

#include <EEPROM.h>
const int inPin = 6;     // the number of the pushbutton pin
const int ledPin =  7;      // the number of the LED pin
int buttonState = 0; // variable for reading the pushbutton status

// what's the name of the hardware serial port?
#define GPSSerial Serial1

void setup() {
  // put your setup code here, to run once:
  // initialize the pushbutton pin as an input:
  pinMode(inPin, INPUT);
  pinMode(ledPin, OUTPUT);
   // 9600 baud is the default rate for the Ultimate GPS
  GPSSerial.begin(9600);
  
}

void loop() {
  // put your main code here, to run repeatedly:
  buttonState = digitalRead(inPin);
  if (buttonState == HIGH) {
    //GPSSerial.begin(9600);
    digitalWrite(ledPin, HIGH);
    if (GPSSerial.available()) {
      char c = GPSSerial.read();
      Serial.write(c);
    } 
  }
  else {
    digitalWrite(ledPin, LOW);
    //GPSSerial.begin(9600);
  }

}





Group 1 - Blog 3

The code for the OLED display project has been finalized, and it is as follows: /*********************************************************...