AGS aka Haiku Shake is a haiku generator. Tilting to the left begins the trickling of the haiku. Each haiku is generated randomly based on 3 haiku forms and a set of preselected words. To generate a new haiku, just shake it.
AGS : HaikuShake V01 from che-wei wang on Vimeo.
Verson 01 features:
-tiny word set (to be expanded)
-uses flash memory to store words (PROGMEM)
-syllable checking for haiku form
-single haiku form (to be expanded to 3)
-simple article choosing function between ‘a’ or ‘an’
-trickling text based on tilt
-shake sensor to generate a new haiku
Arduino Code
//AGS:HaikuShake V01
/*
haiku:
form1:
article adjective noun
article noun verb preposition article noun
adjective adjective noun
form2:
noun preposition article noun
article adjective noun preposition article noun
adjective noun
form3:
article adjective adjective noun
preposition article adjective noun
article noun verb
*/
//hardware connections
/*
tiltX to analog 0
tiltY to analog 1
LCD power to digital 2
LCD rx to tx (digital 1)
*/
#include //for PROGMEM
////////////////////////////////////////////////////
//nouns
prog_char noun_0[] PROGMEM = "breeze ";
prog_char noun_1[] PROGMEM = "moon ";
prog_char noun_2[] PROGMEM = "rain ";
prog_char noun_3[] PROGMEM = "wind ";
prog_char noun_4[] PROGMEM = "sea ";
prog_char noun_5[] PROGMEM = "sky ";
prog_char noun_6[] PROGMEM = "storm ";
prog_char noun_7[] PROGMEM = "water ";
prog_char noun_8[] PROGMEM = "finger ";
prog_char noun_9[] PROGMEM = "sandwich ";
prog_char noun_10[] PROGMEM = "monkey ";
prog_char noun_11[] PROGMEM = "tree ";
prog_char noun_12[] PROGMEM = "wind ";
prog_char noun_13[] PROGMEM = "peace ";
prog_char noun_14[] PROGMEM = "love ";
prog_char noun_15[] PROGMEM = "clock ";
prog_char noun_16[] PROGMEM = "grapefruit ";
prog_char noun_17[] PROGMEM = "cloud ";
prog_char noun_18[] PROGMEM = "ocean ";
prog_char noun_19[] PROGMEM = "fog ";
prog_char noun_20[] PROGMEM = "wave ";
prog_char noun_21[] PROGMEM = "treasure ";
prog_char noun_22[] PROGMEM = "island ";
prog_char noun_23[] PROGMEM = "harmony ";
prog_char noun_24[] PROGMEM = "speaker ";
prog_char noun_25[] PROGMEM = "care ";
prog_char noun_26[] PROGMEM = "trail ";
prog_char noun_27[] PROGMEM = "twinkle ";
prog_char noun_28[] PROGMEM = "flower ";
prog_char noun_29[] PROGMEM = "forrest ";
int nounSyllables[]={
1,1,1,1,1,1,1,2,2,2,2,
1,1,1,1,1,2,1,2,1,1,
2,2,3,2,1,1,2,2,2
};
int nounLength=30;
PGM_P PROGMEM noun_table[]={
noun_0, noun_1,noun_2, noun_3, noun_4, noun_5, noun_6, noun_7, noun_8, noun_9, noun_10,
noun_11,noun_12, noun_13, noun_14, noun_15, noun_16, noun_17, noun_18, noun_19, noun_20,
noun_21,noun_22, noun_23, noun_24, noun_25, noun_26, noun_27, noun_28, noun_29};
//adjectives
prog_char adj_0[] PROGMEM = "liquid ";
prog_char adj_1[] PROGMEM = "gusty ";
prog_char adj_2[] PROGMEM = "flowing ";
prog_char adj_3[] PROGMEM = "brutal ";
prog_char adj_4[] PROGMEM = "hidden ";
prog_char adj_5[] PROGMEM = "bitter ";
prog_char adj_6[] PROGMEM = "misty ";
prog_char adj_7[] PROGMEM = "simple ";
prog_char adj_8[] PROGMEM = "cute ";
prog_char adj_9[] PROGMEM = "adorable ";
prog_char adj_10[] PROGMEM = "pretty ";
prog_char adj_11[] PROGMEM = "perfect ";
prog_char adj_12[] PROGMEM = "white ";
prog_char adj_13[] PROGMEM = "shiny ";
prog_char adj_14[] PROGMEM = "blue ";
int adjSyllables[]={
2,2,2,2,2,2,2,2,1,4,2,
2,1,2,1};
int adjLength=15;
PGM_P PROGMEM adj_table[]={
adj_0, adj_1, adj_2, adj_3, adj_4, adj_5, adj_6, adj_7,adj_8,adj_9 ,adj_10,
adj_11, adj_12, adj_13, adj_14 };
//verbs
prog_char verb_0[] PROGMEM = "shakes ";
prog_char verb_1[] PROGMEM = "drifts ";
prog_char verb_2[] PROGMEM = "has stopped ";
prog_char verb_3[] PROGMEM = "struggles ";
prog_char verb_4[] PROGMEM = "whispers ";
prog_char verb_5[] PROGMEM = "grows ";
prog_char verb_6[] PROGMEM = "flies ";
prog_char verb_7[] PROGMEM = "rips ";
prog_char verb_8[] PROGMEM = "shears ";
prog_char verb_9[] PROGMEM = "hugs ";
prog_char verb_10[] PROGMEM = "kisses ";
prog_char verb_11[] PROGMEM = "touches ";
prog_char verb_12[] PROGMEM = "skips ";
prog_char verb_13[] PROGMEM = "hops ";
prog_char verb_14[] PROGMEM = "smiles ";
int verbSyllables[]={
1,1,2,2,2,1,1,1,1,1,2,
2,1,1,1};
int verbLength=15;
PGM_P PROGMEM verb_table[]={
verb_0,verb_1,verb_2,verb_3,verb_4,verb_5,verb_6,verb_7,verb_8,verb_9,verb_10,
verb_11,verb_12,verb_13,verb_14 };
//articles
prog_char art_0[] PROGMEM = "a ";
prog_char art_1[] PROGMEM = "an ";
prog_char art_2[] PROGMEM = "this ";
prog_char art_3[] PROGMEM = "that ";
prog_char art_4[] PROGMEM = "either ";
prog_char art_5[] PROGMEM = "which ";
prog_char art_6[] PROGMEM = "the ";
int artSyllables[]={
1,1,1,1,2,1};
int artLength=6;
PGM_P PROGMEM art_table[]={
art_0,art_1,art_2,art_3,art_4,art_5,art_6};
//prepositions
prog_char prep_0[] PROGMEM = "of ";
prog_char prep_1[] PROGMEM = "to ";
prog_char prep_2[] PROGMEM = "in ";
prog_char prep_3[] PROGMEM = "for ";
prog_char prep_4[] PROGMEM = "on ";
prog_char prep_5[] PROGMEM = "from ";
prog_char prep_6[] PROGMEM = "with ";
prog_char prep_7[] PROGMEM = "as ";
prog_char prep_8[] PROGMEM = "by ";
int prepSyllables[]={
1,1,1,1,1,1,1,1,1};
int prepLength=9;
PGM_P PROGMEM prep_table[]={
prep_0,prep_1,prep_2,prep_3,prep_4,prep_5,prep_6,prep_7,prep_8};
////////////////////////////////////////////////////
// make sure this is large enough for the largest string it must hold
char bufferA[15];
char bufferB[15];
char bufferC[15];
char bufferD[15];
char bufferE[15];
char bufferF[15];
char bufferG[15];
char bufferH[15];
char bufferI[15];
char bufferJ[15];
char bufferK[15];
char bufferL[15];
int form=0;
int r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12; //random numbers
int line0Total,line1Total,line2Total=0; //haiku syllable line totals
boolean home=false; //go to top of program
boolean newForm=true;
int scrollCount=0;
//tilt
int x0, y0, x, y;
boolean zero=false;
long resTimer=0; //sensor timer
long tiltTimer=0;
boolean shaken=false;
void clearBuffers(){
for( int i=0;i<15;i++){
bufferA[i]=NULL;
bufferB[i]=NULL;
bufferC[i]=NULL;
bufferD[i]=NULL;
bufferE[i]=NULL;
bufferF[i]=NULL;
bufferG[i]=NULL;
bufferH[i]=NULL;
bufferI[i]=NULL;
bufferJ[i]=NULL;
bufferK[i]=NULL;
bufferL[i]=NULL;
}
}
void reset(){
clearLCD();
//set display brightness
Serial.print(124,BYTE);//command header
Serial.print(129,BYTE);//display brightness 129-
//while( checkShake() )delay(100);
//reset line totals
line0Total=0;
line1Total=0;
line2Total=0;
clearBuffers();
newForm=true;
home=true;
delay(100);
}
void setup(){
pinMode(2,OUTPUT);
Serial.begin(9600);
//splash toggle
//Serial.print(124,BYTE);//command header
//Serial.print(9,BYTE);//toggle splash
}
void formBuffer(int form, int line){
if(form==0){
int lineTotal=0;
//reset buffers
//generate random values to select words
if(line==0){
while (lineTotal!=5){//continue random selection until syllable total is 5
//article adjective noun
int ra=getRandom(artLength) ;
int rb=getRandom(adjLength);
int rc=getRandom(nounLength);
strcpy_P(bufferA, (char*)pgm_read_word(&(art_table[ra] ))); // Necessary casts and dereferencing, just copy.
strcpy_P(bufferB, (char*)pgm_read_word(&(adj_table[rb] )));
strcpy_P(bufferC, (char*)pgm_read_word(&(noun_table[rc] )));
switchArticle(bufferA,bufferB);
//check syllable count
lineTotal=artSyllables[ra]+adjSyllables[rb]+nounSyllables[rc];
}
}
else if(line==1){
while (lineTotal!=7){//continue random selection until syllable total is 5
//article noun verb preposition article noun
int ra=getRandom(artLength) ;
int rb=getRandom(nounLength);
int rc=getRandom(verbLength);
int rd=getRandom(prepLength) ;
int re=getRandom(artLength);
int rf=getRandom(nounLength);
strcpy_P(bufferD, (char*)pgm_read_word(&(art_table[ra] )));
strcpy_P(bufferE, (char*)pgm_read_word(&(noun_table[rb] )));
strcpy_P(bufferF, (char*)pgm_read_word(&(verb_table[rc] )));
strcpy_P(bufferG, (char*)pgm_read_word(&(prep_table[rd] )));
strcpy_P(bufferH, (char*)pgm_read_word(&(art_table[re] )));
strcpy_P(bufferI, (char*)pgm_read_word(&(noun_table[rf] )));
switchArticle(bufferD,bufferE);
switchArticle(bufferH,bufferI);
lineTotal=artSyllables[ra]+nounSyllables[rb]+verbSyllables[rc]+prepSyllables[rd]+artSyllables[re]+nounSyllables[rf];
}
}
else if(line==2){
while (lineTotal!=5){//continue random selection until syllable total is 5
//adjective adjective noun
int ra=getRandom(adjLength) ;
int rb=getRandom(adjLength);
int rc=getRandom(nounLength);
strcpy_P(bufferJ, (char*)pgm_read_word(&(adj_table[ra] )));
strcpy_P(bufferK, (char*)pgm_read_word(&(adj_table[rb] )));
strcpy_P(bufferL, (char*)pgm_read_word(&(noun_table[rc] )));
switchArticle(bufferK,bufferL);
lineTotal=adjSyllables[ra]+adjSyllables[rb]+nounSyllables[rc];
}
}
}
}
int getRandom( int length ){
delay(15);
randomSeed(analogRead(5));
return random(length);
}
int printBuffer(int pos, char* buffer){
int j=0;
int cursor;
//print each character from buffer while not NULL
while(buffer[j]!=NULL){
cursor=pos+j;
//trickle left text
int k;
if(tiltLeft()){
if(cursor<64)k=15-cursor;
else if(cursor>=64)k=78-cursor;
while(cursor+k>=cursor){
k--;
cursorPos(cursor+k+1);
Serial.print( buffer[j]);
delay(constrain(55+x,1,60));
cursorPos(cursor+k+1);
Serial.print(' ');
}
cursorPos(cursor);
Serial.print( buffer[j] );
j++;
}
else if (tiltRight() && j>0){
k=-1;
while(cursor<64 && cursor+k<=15 || cursor>=64 && cursor+k<=79+scrollCount){
k++;
cursorPos(cursor+k-1);
Serial.print( buffer[j-1]);
delay(constrain(55-x,1,60));
cursorPos(cursor+k-1);
Serial.print(' ');
}
j--;
if(j<0)j=0;
}
//scroll if text runs off
if(cursor>16 && cursor<64){
scrollL();
scrollCount++;
}
if( cursor>80+scrollCount ) scrollL();
//pause if flat
while(tiltLeft()==false && tiltRight()==false){
delay(5);
if(checkShake()){
reset();
break;
}
}
if(checkShake()){
reset();
break;
}
}
//pause after each word
long t=millis();
while(millis()-t
if( checkShake() )reset();
}
return cursor+1;
}
void loop(){
home=false; //at the top of the page
long t;
// zero tilt sensor
if(zero==false){
delay(300);
setZero();
reset();
splash();
}
//LINE00///////////////////////////////////////////
if(newForm==true){
formBuffer(0,0);
formBuffer(0,1);
formBuffer(0,2);
newForm=false;
}
while(home==false){
fadeIn();
int cursor=0;
cursor=printBuffer(cursor,bufferA);
cursor=printBuffer(cursor,bufferB);
cursor=64;
cursor=printBuffer(cursor,bufferC);
t=millis();
while(millis()-t<1000){
if( checkShake() ){
reset();
break;
}
}
if(home==true) break;
while(tiltLeft()==false){
delay(5);
}
fadeOut();
clearLCD();
//LINE01/////////////////////////////////////
//article noun verb preposition article noun
fadeIn();
cursor=0;
cursor=printBuffer(cursor,bufferD);
cursor=printBuffer(cursor,bufferE);
cursor=printBuffer(cursor,bufferF);
cursor=64+scrollCount;
cursor=printBuffer(cursor,bufferG);
cursor=printBuffer(cursor,bufferH);
cursor=printBuffer(cursor,bufferI);
scrollCount=0;
t=millis();
while(millis()-t<1000){
if( checkShake() ){
reset();
break;
}
}
if(home==true) break;
if(tiltLeft()==false){
delay(10);
}
fadeOut();
clearLCD();
//LINE02//////////////////////////////////
//adjective adjective noun
fadeIn();
cursor=0;
cursor=printBuffer(cursor,bufferJ);
cursor=printBuffer(cursor,bufferK);
cursor=64;
cursor=printBuffer(cursor,bufferL);
if(tiltLeft()==false){
delay(5);
}
t=millis();
while(millis()-t<1000){
if( checkShake() ){
reset();
break;
}
}
if(home==true) break;
fadeOut();
clearLCD();
t=millis();
while(millis()-t<3000){
if( checkShake() ){
reset();
break;
}
}
if(home==true) break;
if( checkShake() ){
reset();
break;
}
}
}
///////////////////////////////////////////
boolean tiltLeft(){
boolean tilt;
// if(millis()-tiltTimer>50){
readTilt();
if(x<-10){
tilt=true;
}
else{
tilt=false;
}
// tiltTimer=millis();
//}
return tilt;
}
boolean tiltRight(){
boolean tilt;
//if(millis()-tiltTimer>50){
readTilt();
if(x>10){
tilt=true;
}
else{
tilt=false;
}
//tiltTimer=millis();
// }
return tilt;
}
void switchArticle(char* article, char* object){
if(checkVowel(object[0])){
if (article[0]=='a' && article[1]==' '){
article[1]=='n';
article[2]==' '; //space after text
article[3]==NULL; //null for end of characters
}
}
else{
if (article[0]=='a' && article[1]=='n'){
article[1]=' ';
article[2]=NULL;
}
}
}
boolean checkVowel(char buffer){
boolean check;
if(buffer=='a' || buffer=='e' || buffer=='i' || buffer=='o' || buffer=='u'){
check=true;
}
else check=false;
return check;
}
boolean checkShake(){
boolean check;
int thres=150;
if(millis()-resTimer>5000){
readTilt();
if(y>thres || y<-thres || x>thres || x<-thres){
// reset();
check=true;
resTimer=millis();
}
else{
check=false;
}
}
return check;
}
void splash(){
fadeIn();
char ags[]={
"AGS : HaikuShake V01" };
Serial.print(ags);
delay(1000);
fadeOut();
clearLCD();
cursorPos(0);
delay(500);
}
void readTilt(){
x=analogRead(0)-x0; //reads and represents acceleration X
y=analogRead(1)-y0; //reads and represents acceleration Y
}
//zero all tilt sensors
void setZero(){
x0=analogRead(0);
y0=analogRead(1);
zero=true;
}
void fadeIn(){
long fade=0;
while(fade<=28){
Serial.print(124,BYTE);//command header
int brightness=129+fade;
Serial.print(brightness,BYTE);//128-157 brightness
delay(10);
fade++;
}
}
void fadeOut(){
long fade=0;
while(fade<=30){
Serial.print(124,BYTE);//command header
int brightness=159-fade;
Serial.print(brightness,BYTE);//128-157 brightness
delay(10);
fade++;
}
delay(10);
}
void selectLineOne(){ //puts the cursor at line 0 char 0.
Serial.print(0xFE, BYTE); //command flag
Serial.print(128, BYTE); //position
}
void selectLineTwo(){ //puts the cursor at line 0 char 0.
Serial.print(0xFE, BYTE); //command flag
Serial.print(192, BYTE); //position
}
void clearLCD(){
Serial.print(0xFE, BYTE); //command flag
Serial.print(0x01, BYTE); //clear command.
}
void backlightOn(){ //turns on the backlight
Serial.print(0x7C, BYTE); //command flag for backlight stuff
Serial.print(157, BYTE); //light level.
}
void backlightOff(){ //turns off the backlight
Serial.print(0x7C, BYTE); //command flag for backlight stuff
Serial.print(128, BYTE); //light level for off.
}
void serCommand(){ //a general function to call the command flag for issuing all other commands
Serial.print(0xFE, BYTE);
}
void cursorR(){
Serial.print(0xFE, BYTE);
Serial.print(0x14, BYTE);
}
void cursorL(){
Serial.print(0xFE, BYTE);
Serial.print(0x10, BYTE);
}
void scrollR(){
Serial.print(0xFE, BYTE);
Serial.print(0x1C, BYTE);
}
void scrollL(){
Serial.print(0xFE, BYTE);
Serial.print(0x18, BYTE);
}
void cursorPos(int pos){
Serial.print(0xFE, BYTE);
Serial.print(128+pos, BYTE);
}
*10.0){>
Very cool. I love your uses of accelerometers, I really need to get my hands dirty with using those!