Hackster is hosting Hackster Holidays, Finale: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Tuesday!Stream Hackster Holidays, Finale on Tuesday!
ctKiyana SalkeldEmon MotamediJulianne C
Published

Scroller

an attention-grabbing platform to broadcast the news.

Full instructions provided921
Scroller

Things used in this project

Hardware components

Baby
×1
Acrylic
×2
Electret Microphone Amplifier
×1
9v Battery
×1
P7.62 32X8 Green LED Dot Matrix Unit Board
×2
stroller
×1
lil squishy chickadee
×1

Story

Read more

Code

cryMeARiver.ino

C/C++
cryMeARiver.ino
#include <string.h>
#include "MatrixDisplay.h"
#include "DisplayToolbox.h"
#include "font.h"
#include "PS2Keyboard.h"

const int numLines = 6;        // Max number of lines
const int displayTime = 1500;  // Length of time in milliseconds to display each line
const int gapTime = 10;        // Time gap between lines
const int maxLineLength = 100; // Maximum length of a line in characters
const int scrollDelay = 0;

String textLines[numLines];     // Array of text lines
String displayText[1];

int textLength;          // Holds current line length in pixels
int strLength;           // Holds current line length in characters
int currentLine = 0;     // Index of current line

int mode = 1;            // Determines whether in input (1) or output (2) mode

char defaultText[numLines][30] = {{"Hello World!"},{"Welcome to Cry Me A River"}};

char badArray[][100] = {{"Putin annexes Crimea, Ukraine cries robbery"}, 
                         {"Suicide bomber kills at least three in Northern Afghanistan"}, 
                         {"Families of flight 370 passengers hold vigil"},
                         {"Wailing mom of flight 370 passenger dragged from briefing room"}, 
                         {"Israel troops kill 15 year-old Palestinian in W Bank"}, 
                         {"Blast near college in Pakistan kills 10"}, 
                         {"Israel Bombs Syrian Posts Following Golan Heights Attack"}};
                         
// Character lookup string -- used to map the characters from the keyboard onto the font data array
// (This should probably be moved to program memory in some form in the future)
String charLookup  = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*(),-.?></\\|[]_=+:'\"{}";

// Memory test
extern int __bss_end;
extern int *__brkval;

/* DISPLAY LIBRARY SETUP */

// Parameters for Matrix Display initialization:
// Number of displays = 3
// Data pin = 10 
// WR pin == 11
// Shadow buffer = true

// Macro to make it the initDisplay function a little easier to understand
#define setMaster(dispNum, CSPin) initDisplay(dispNum,CSPin,true)
#define setSlave(dispNum, CSPin) initDisplay(dispNum,CSPin,false)

// Initialize matrix
MatrixDisplay disp(2,11,10, true);
DisplayToolbox toolbox(&disp);

// Prepare boundaries
uint8_t X_MAX = 0;
uint8_t Y_MAX = 0;


/* KEYBOARD SETUP */

#define KBD_CLK_PIN  3
#define KBD_DATA_PIN 7

#define is_printable(c) (!(c&0x80))   

PS2Keyboard keyboard;



const double BAD = 1;
const double WORSE = 1.5;
const double TRAGIC= 3;
int badCounter = 0;
int worseCounter = 0;
int tragicCounter = 0;




void setup() { 
 
  Serial.begin(9600);  
  
  for(int i=0; i<numLines; i++){
    textLines[i] = defaultText[i];
    Serial.println(defaultText[i]);
  }
  
  // Initialize the keyboard class
  //keyboard.begin(KBD_DATA_PIN); 
  
  displayText[0] = badArray[0];
  // Fetch display bounds 
  X_MAX = disp.getDisplayCount() * (disp.getDisplayWidth()-1)+3;
  Y_MAX = disp.getDisplayHeight()-1;
 
  // Prepare displays
  disp.setMaster(0,4);
  disp.setSlave(1,5);
  //disp.setSlave(2,6);
}

void loop() {
  
  //strLength = textLines[currentLine].length(); // Number of characters in the string
  //textLength = (strLength*6); // Width of string in pixels
  strLength = displayText[0].length();
  
  textLength = (strLength*6);
  // Convert the String into a char array
  char* text; 
  char textMem[maxLineLength];
  for(int i=0;i<maxLineLength;i++){
    //textMem[i]=textLines[currentLine][i];
    textMem[i]= displayText[0][i];
  }
  text = textMem;
  
  
  if(mode == 2){ // Output mode
     if(strLength > 1){
       if(textLength < (X_MAX +1)){
         fixedText(text);
         delay(displayTime);
         disp.clear(); 
         disp.syncDisplays();
         delay(gapTime); 
       }else{
         scrollText(text); 
         delay(gapTime);
       }
     }
     //nextLine();
     mode = 1;
  }else{ // Input mode
    
    pollMicrophone();
    
    
  }
}

//TODO: Set displayText
void pollMicrophone(){
   unsigned long startMillis= millis();  // Start of sample window
   unsigned int peakToPeak = 0;   // peak-to-peak level
   unsigned int sampleWindow = 50;
   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;
   
   // collect data for 50 mS
   while (millis() - startMillis < sampleWindow)
   {
      int sample = analogRead(A5);
      if (sample < 1024)  // toss out spurious readings
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save just the min levels
         }
      }
   }
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   double volts = (peakToPeak * 3.3) / 1024;  // convert to volts
   //Serial.println(volts);
   
   //TODO: interpret the reading (volts) as being BAD/WORSE/TRAGEDY
  if (volts >=BAD && volts <=WORSE){
     
     
     //Serial.println(volts);
     if (worseCounter > 0 || tragicCounter > 0) {
       worseCounter = 0;
       tragicCounter = 0;
     }
     badCounter++;
     if (badCounter == 3) {
       
        mode = 2;
        //Serial.println(badArray[value]);
        displayText[0] = badArray[currentLine];
        currentLine++;
        //Serial.println(displayText);
        //Serial.println(badArray[random(0, 3)]); //This should be Jose's method, not a print statement
        //delay(10000);
        badCounter = 0;
     }
   }
   else if (volts >=WORSE && volts <=TRAGIC){
     
     
     //Serial.println(volts);
     if (badCounter > 0 || tragicCounter > 0) {
       badCounter = 0;
       tragicCounter = 0;
     }
     worseCounter++;
     if (worseCounter == 3) {
       Serial.println("WORSE");
        mode = 2;
        displayText[0] = badArray[currentLine];
        currentLine++;
        //Serial.println(worseArray[value]);
        //displayText[0] = worseArray[value];
        //Serial.println(displayText);
        //Serial.println(worseArray[random(0, 3)]); //This should be Jose's method, not a print statement
        //delay(10000);
        worseCounter = 0;
     }
   }
   else if (volts >=TRAGIC){
     
     
     //Serial.println(volts);
     if (badCounter > 0 || worseCounter > 0) {
       badCounter = 0;
       worseCounter = 0;
     }
     tragicCounter++;
     if (tragicCounter == 3) {
       Serial.println("TRAGEDY");
        mode = 2;
        displayText[0] = badArray[currentLine];
        currentLine++;
        //Serial.println(tragicArray[value]);
        //displayText[0] = tragicArray[value];
        //Serial.println(displayText);
        //Serial.println(tragicArray[random(0, 3)]); //This should be Jose's method, not a print statement
       //delay(10000);
       tragicCounter = 0;
     }
   }
   else {
     mode = 1; 
   }
   
   if (currentLine > 6) {
      currentLine = 0; 
   }
   delay(2);
}

void nextLine(){
   if(currentLine < (numLines -1)){
      currentLine++; 
   }else{
     currentLine = 0;
   }    
}

void prevLine(){
  if(currentLine > 0){
     currentLine--; 
  } else {
     currentLine = (numLines -1);
  }
}


// Scroll a line of text across the display

/* This is a fairly inefficient function. It uses drawString() to 
redraw repeatedly as it moves. Not a problem in this case, but if 
faster scrolling was needed it should probably be rewritten to use 
disp.shiftLeft() instead */

void scrollText(char* text){
  int y=1;
  int endPos = 0 - textLength;
  int loopCount = 0;
  for(int Xpos = X_MAX; Xpos > endPos; Xpos--){
    loopCount++;
    disp.clear();
    drawString(Xpos,y,text); 
    disp.syncDisplays();
    delay(scrollDelay); 
  }
}


// Write a line of static (non-scrolling) text to the display
void fixedText(char* text){
  int y = 1;
  int x = 0;
  disp.clear();
  drawString(x,y,text);
  disp.syncDisplays(); 
}


// Output a string to the display
void drawString(int x, uint8_t y, char* c){
  for(char i=0; i< strLength; i++){
    drawChar(x, y, c[i]);
    x+=6; // Width of each glyph
  }
}


// Output a single character to the display
void drawChar(int x, int y, char c){
  int dots;
  
  c = charLookup.indexOf(c);
  
  for (char col=0; col< 5; col++) {
    if((x+col+1)>0 && x < X_MAX){ // dont write to the display buffer if the location is out of range
      dots = pgm_read_byte_near(&myfont[c][col]);
      for (char row=0; row < 7; row++) {
        if (dots & (64>>row))   	     // only 7 rows.
          toolbox.setPixel(x+col, y+row, 1);
        else 
          toolbox.setPixel(x+col, y+row, 0);
      }
    }
  }
}

// Warn if we're running out of RAM
void low_memory_alert(){
  for(int i=0; i < 3; i++){
    int y = 1;
    int x = 0;
    disp.clear();
    drawString(x,y,"   MEMORY LOW!  ");
    disp.syncDisplays();
    delay(500);
    disp.clear();
    disp.syncDisplays();
    delay(500);
    disp.clear();
  }
}

// Memory check
int get_free_memory(){
  int free_memory;
  if((int)__brkval == 0)
    free_memory = ((int)&free_memory) - ((int)&__bss_end);
  else
    free_memory = ((int)&free_memory) - ((int)__brkval);
    Serial.println(free_memory);
  return free_memory;
}

Credits

ct
5 projects • 4 followers
Kiyana Salkeld
4 projects • 3 followers
Senior double majoring in Computer Science and Cognitive Science
Emon Motamedi
4 projects • 3 followers
Julianne C
3 projects • 1 follower

Comments