uncanny eyes with Teensy 3.1

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
rogerc2288
 
Posts: 5
Joined: Thu Jul 25, 2013 11:04 am

uncanny eyes with Teensy 3.1

Post by rogerc2288 »

I was able to get the 'blink' sketch to work as stated in the project but when I try to verify the animated eyes code I get this error:

Arduino: 1.6.5 (Windows 7), TD: 1.25, Board: "Teensy 3.2 / 3.1, Serial, 72 MHz optimized, US English"

uncannyEyes.ino:453:17: warning: extra tokens at end of #ifdef directive [enabled by default]
uncannyEyes.ino: In function 'void setup()':
uncannyEyes:99: error: 'INITR_144GREENTAB' was not declared in this scope
uncannyEyes.ino: In function 'void frame(uint16_t)':
uncannyEyes.ino:320:67: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
uncannyEyes.ino:397:33: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
'INITR_144GREENTAB' was not declared in this scope

Any ideas?

User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: uncanny eyes with Teensy 3.1

Post by adafruit_support_mike »

From the errors, it looks like you have some garbage characters in the sketch.

Post the exact code you're using (between CODE tags please) and we'll see what we can find.

User avatar
rogerc2288
 
Posts: 5
Joined: Thu Jul 25, 2013 11:04 am

Re: uncanny eyes with Teensy 3.1

Post by rogerc2288 »

Thanks for the help. When trying to verify, the forth line is highlighted and I get the error message. I downloaded the code into the Arduino IDE (1.6.5) and ran it without making any changes.

Code: Select all

 // For some reason display #1 must init first, else jumbled.  WTH?
  for(uint8_t e=NUM_EYES; e--; ) { // Work last-to-first
#ifdef _ADAFRUIT_ST7735H_ // TFT
    eye[e].display.initR(INITR_144GREENTAB);
#else // OLED
    eye[e].display.begin();
#endif
    if(eye[e].blink.pin >= 0) pinMode(eye[e].blink.pin, INPUT_PULLUP);
  }
#ifdef BLINK_PIN
  pinMode(BLINK_PIN, INPUT_PULLUP);
#endif
Last edited by adafruit_support_mike on Wed Sep 30, 2015 10:32 pm, edited 1 time in total.
Reason: added CODE tags to preserve formatting

User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: uncanny eyes with Teensy 3.1

Post by adafruit_support_mike »

Try downloading a new copy of the ST7735 library. It looks like you have a version that's missing a hardware identifier.

https://github.com/adafruit/Adafruit-ST7735-Library

User avatar
_chris_
 
Posts: 1
Joined: Fri Oct 02, 2015 11:52 am

Re: uncanny eyes with Teensy 3.1

Post by _chris_ »

I had the same issue. Turns out, like mike said, the libraries were at fault. I had originally installed the libraries with the teensyduino package (I'm on OS X), but that caused the compile error. I went in and removed those libraries (buried in /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries) and installed the ones from the arduino library manager and everything is up and running ...

User avatar
rogerc2288
 
Posts: 5
Joined: Thu Jul 25, 2013 11:04 am

Re: uncanny eyes with Teensy 3.1

Post by rogerc2288 »

Many thanks to both of you: Mike and Chris!! It looks like removing those libraries and re-installing them will do it. I don't have the hardware all completed yet but at least the code is verifying and uploading to the teensy.

User avatar
pmd2000
 
Posts: 7
Joined: Wed Aug 13, 2014 8:18 am

Re: uncanny eyes with Teensy 3.1

Post by pmd2000 »

Thanks to all at Adafruit for writing the uncanny eyes. Just got my TFT's in and teensy up and running. Without the forum for a quick ref and fix woulda taken me a long time.

I plan to scare lots and lots of folks with these!!!

Thanks again Lady Ada and your fab staff!

User avatar
rbbtebo
 
Posts: 57
Joined: Tue Aug 18, 2015 9:12 am

Re: uncanny eyes with Teensy 3.1

Post by rbbtebo »

Got mine working last night with OLED. These, along with my firewalker shoes are fantastic. Love Adafruit!

User avatar
Bwholt
 
Posts: 5
Joined: Sun Jan 05, 2014 11:46 am

Re: uncanny eyes with Teensy 3.1

Post by Bwholt »

Hi. I've downloaded the latest ST7735 TFT library from the Github repository but I still get compile errors as shown below. I've deleted all other references/locations of the ST7735 library files from my system and only the latest version exists in my Arduino library. I've restarted the IDE multiple times, checked the libraries and all looks as it should be but I can't get past this nebulous compile error. Please help!

Code: Select all

Arduino: 1.6.5 (Windows 7), TD: 1.25, Board: "Teensy 3.2 / 3.1, Serial, 72 MHz optimized, US English"

Using library SPI in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SPI (1.0.x format)

Using library Adafruit GFX Library in folder: C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-GFX 

Using library Adafruit ST7735 Library in folder: C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735 



C:\Program Files (x86)\Arduino/hardware/tools/arm/bin/arm-none-eabi-g++ -c -O -g -Wall -ffunction-sections -fdata-sections -MMD -nostdlib -fno-exceptions -felide-constructors -std=gnu++0x -fno-rtti -mthumb -mcpu=cortex-m4 -fsingle-precision-constant -D__MK20DX256__ -DTEENSYDUINO=125 -DARDUINO=10605 -DF_CPU=72000000 -DARDUINO_ARCH_AVR -DUSB_SERIAL -DLAYOUT_US_ENGLISH -IC:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy3 -IC:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SPI -IC:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-GFX -IC:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735 C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\uncannyEyes.cpp -o C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\uncannyEyes.cpp.o 

uncannyEyes.ino:460:17: warning: extra tokens at end of #ifdef directive [enabled by default]
In file included from uncannyEyes.ino:21:0:
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
0X007F, 0X007F, 0X007F, 0X007F, 0X007F, 0X007F, 0X007F, 0X007F };
^
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
C:\Users\BWHOLT~1.NET\AppData\Local\Temp\build6694199665238610382.tmp\dragonEye.h:15637:66: warning: narrowing conversion of '-1' from 'int' to 'const uint16_t {aka const short unsigned int}' inside { } [-Wnarrowing]
In file included from uncannyEyes.ino:28:0:
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:175:12: error: 'RwReg' does not name a type
volatile RwReg  *dataport, *clkport, *csport, *rsport;
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:176:16: error: redeclaration of 'uint32_t Adafruit_ST7735::_cs'
uint32_t  _cs, _rs, _sid, _sclk,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:169:12: note: previous declaration 'uint8_t Adafruit_ST7735::_cs'
uint8_t  _cs, _rs, _rst, _sid, _sclk,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:176:21: error: redeclaration of 'uint32_t Adafruit_ST7735::_rs'
uint32_t  _cs, _rs, _sid, _sclk,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:169:17: note: previous declaration 'uint8_t Adafruit_ST7735::_rs'
uint8_t  _cs, _rs, _rst, _sid, _sclk,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:176:27: error: redeclaration of 'uint32_t Adafruit_ST7735::_sid'
uint32_t  _cs, _rs, _sid, _sclk,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:169:28: note: previous declaration 'uint8_t Adafruit_ST7735::_sid'
uint8_t  _cs, _rs, _rst, _sid, _sclk,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:176:34: error: redeclaration of 'uint32_t Adafruit_ST7735::_sclk'
uint32_t  _cs, _rs, _sid, _sclk,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:169:34: note: previous declaration 'uint8_t Adafruit_ST7735::_sclk'
uint8_t  _cs, _rs, _rst, _sid, _sclk,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:177:24: error: redeclaration of 'uint32_t Adafruit_ST7735::datapinmask'
datapinmask, clkpinmask, cspinmask, rspinmask,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:170:12: note: previous declaration 'uint8_t Adafruit_ST7735::datapinmask'
datapinmask, clkpinmask, cspinmask, rspinmask,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:177:36: error: redeclaration of 'uint32_t Adafruit_ST7735::clkpinmask'
datapinmask, clkpinmask, cspinmask, rspinmask,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:170:25: note: previous declaration 'uint8_t Adafruit_ST7735::clkpinmask'
datapinmask, clkpinmask, cspinmask, rspinmask,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:177:47: error: redeclaration of 'uint32_t Adafruit_ST7735::cspinmask'
datapinmask, clkpinmask, cspinmask, rspinmask,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:170:37: note: previous declaration 'uint8_t Adafruit_ST7735::cspinmask'
datapinmask, clkpinmask, cspinmask, rspinmask,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:177:58: error: redeclaration of 'uint32_t Adafruit_ST7735::rspinmask'
datapinmask, clkpinmask, cspinmask, rspinmask,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:170:48: note: previous declaration 'uint8_t Adafruit_ST7735::rspinmask'
datapinmask, clkpinmask, cspinmask, rspinmask,
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:178:21: error: redeclaration of 'uint32_t Adafruit_ST7735::colstart'
colstart, rowstart; // some displays need this changed
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:171:12: note: previous declaration 'uint8_t Adafruit_ST7735::colstart'
colstart, rowstart; // some displays need this changed
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:178:23: error: redeclaration of 'uint32_t Adafruit_ST7735::rowstart'
colstart, rowstart; // some displays need this changed
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:171:22: note: previous declaration 'uint8_t Adafruit_ST7735::rowstart'
colstart, rowstart; // some displays need this changed
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:179:13: error: redeclaration of 'int32_t Adafruit_ST7735::_rst'
int32_t   _rst;  // Must use signed type since a -1 sentinel is assigned.
^
C:\Users\BLAH BLAH BLAH\Documents\Arduino\libraries\Adafruit-ST7735/Adafruit_ST7735.h:169:22: note: previous declaration 'uint8_t Adafruit_ST7735::_rst'
uint8_t  _cs, _rs, _rst, _sid, _sclk,
^
uncannyEyes.ino: In function 'void frame(uint16_t)':
uncannyEyes.ino:327:67: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
uncannyEyes.ino:404:33: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
Error compiling.
Last edited by adafruit_support_mike on Wed Oct 14, 2015 1:07 am, edited 1 time in total.
Reason: added CODE tags

User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: uncanny eyes with Teensy 3.1

Post by adafruit_support_mike »

It looks like there's some kind of unexpected character at the end of line 460 in the 'uncannyEyes.ino' sketch.

Post the exact sketch you have (between CODE tags please) and we'll see what we can find.

User avatar
Bwholt
 
Posts: 5
Joined: Sun Jan 05, 2014 11:46 am

Re: uncanny eyes with Teensy 3.1

Post by Bwholt »

I can post the sketch when I return home from work tonight; however, It was a completely unaltered version that was downloaded directly from your website with the exception of changing the display type from OLED to TFT.

Thanks
Wayne

User avatar
Bwholt
 
Posts: 5
Joined: Sun Jan 05, 2014 11:46 am

Re: uncanny eyes with Teensy 3.1

Post by Bwholt »

Mike,

Here's the code I'm trying to compile. Other things I have tried are using a fresh version of the code as downloaded from your website (which is what's below), I've deleted ANY references to the ST7735 library on my system and reinstalled a fresh version of the library from the Github site.

My Arduino IDE is configured for Teensy 3.1/3.2 board, Serial USB type, 72 Mhz optimized and programmer is Arduino as ISP.

Thanks
Wayne

Code: Select all

//--------------------------------------------------------------------------
// Uncanny eyes for PJRC Teensy 3.1 with Adafruit 1.5" OLED (product #1431)
// or 1.44" TFT LCD (#2088).  This uses Teensy-3.1-specific features and
// WILL NOT work on normal Arduino or other boards!  Use 72 MHz (Optimized)
// board speed -- OLED does not work at 96 MHz.
//
// Adafruit invests time and resources providing this open source code,
// please support Adafruit and open-source hardware by purchasing products
// from Adafruit!
//
// Written by Phil Burgess / Paint Your Dragon for Adafruit Industries.
// MIT license.  SPI FIFO insight from Paul Stoffregen's ILI9341_t3 library.
// Inspired by David Boccabella's (Marcwolf) hybrid servo/OLED eye concept.
//--------------------------------------------------------------------------

#include <SPI.h>
#include <Adafruit_GFX.h>      // Core graphics lib for Adafruit displays
// Enable ONE of these #includes -- HUGE graphics tables for various eyes:
#include "defaultEye.h"        // Standard human-ish hazel eye
//#include "noScleraEye.h"       // Large iris, no sclera
//#include "dragonEye.h"         // Slit pupil fiery dragon/demon eye
//#include "goatEye.h"           // Horizontal pupil /Krampus eye
// Then tweak settings below, e.g. change IRIS_MIN/MAX or disable TRACKING.

// DISPLAY HARDWARE CONFIG -------------------------------------------------

//#include <Adafruit_SSD1351.h>  // OLED display library -OR-
#include <Adafruit_ST7735.h> // TFT display library (enable one only)

#ifdef _ADAFRUIT_ST7735H_
typedef Adafruit_ST7735  displayType; // Using TFT display(s)
#else
typedef Adafruit_SSD1351 displayType; // Using OLED display(s)
#endif

#define DISPLAY_DC      7 // Data/command pin for BOTH displays
#define DISPLAY_RESET   8 // Reset pin for BOTH displays
#define SELECT_L_PIN    9 // LEFT eye chip select pin
#define SELECT_R_PIN   10 // RIGHT eye chip select pin

// INPUT CONFIG (for eye motion -- enable or comment out as needed) --------

//#define JOYSTICK_X_PIN A0 // Analog pin for eye horiz pos (else auto)
//#define JOYSTICK_Y_PIN A1 // Analog pin for eye vert position (")
//#define JOYSTICK_X_FLIP   // If set, reverse stick X axis
//#define JOYSTICK_Y_FLIP   // If set, reverse stick Y axis
#define TRACKING          // If enabled, eyelid tracks pupil
#define IRIS_PIN       A2 // Photocell or potentiometer (else auto iris)
//#define IRIS_PIN_FLIP     // If set, reverse reading from dial/photocell
#define IRIS_SMOOTH       // If enabled, filter input from IRIS_PIN
#define IRIS_MIN      120 // Clip lower analogRead() range from IRIS_PIN
#define IRIS_MAX      720 // Clip upper "
#define WINK_L_PIN      0 // Pin for LEFT eye wink button
#define BLINK_PIN       1 // Pin for blink button (BOTH eyes)
#define WINK_R_PIN      2 // Pin for RIGHT eye wink button
#define AUTOBLINK         // If enabled, eyes blink autonomously

// Probably don't need to edit any config below this line, -----------------
// unless building a single-eye project (pendant, etc.), in which case one
// of the two elements in the eye[] array further down can be commented out.

// Eye blinks are a tiny 3-state machine.  Per-eye allows winks + blinks.
#define NOBLINK 0     // Not currently engaged in a blink
#define ENBLINK 1     // Eyelid is currently closing
#define DEBLINK 2     // Eyelid is currently opening
typedef struct {
  int8_t   pin;       // Optional button here for indiv. wink
  uint8_t  state;     // NOBLINK/ENBLINK/DEBLINK
  int32_t  duration;  // Duration of blink state (micros)
  uint32_t startTime; // Time (micros) of last state change
} eyeBlink;

struct {
  displayType display; // OLED/TFT object
  uint8_t     cs;      // Chip select pin
  eyeBlink    blink;   // Current blink state
} eye[] = { // OK to comment out one of these for single-eye display:
  displayType(SELECT_L_PIN,DISPLAY_DC,0),SELECT_L_PIN,{WINK_L_PIN,NOBLINK},
  displayType(SELECT_R_PIN,DISPLAY_DC,0),SELECT_R_PIN,{WINK_R_PIN,NOBLINK},
};
#define NUM_EYES (sizeof(eye) / sizeof(eye[0]))


// INITIALIZATION -- runs once at startup ----------------------------------

void setup(void) {
  uint8_t e;

  Serial.begin(115200);
  randomSeed(analogRead(A3)); // Seed random() from floating analog input

  // Both displays share a common reset line; 0 is passed to display
  // constructor (so no reset in begin()) -- must reset manually here:
  pinMode(DISPLAY_RESET, OUTPUT);
  digitalWrite(DISPLAY_RESET, LOW);  delay(1);
  digitalWrite(DISPLAY_RESET, HIGH); delay(50);

  for(e=0; e<NUM_EYES; e++) { // Deselect all
    pinMode(eye[e].cs, OUTPUT);
    digitalWrite(eye[e].cs, HIGH);
  }
  for(e=0; e<NUM_EYES; e++) {
    digitalWrite(eye[e].cs, LOW); // Select one eye for init
#ifdef _ADAFRUIT_ST7735H_ // TFT
    eye[e].display.initR(INITR_144GREENTAB);
#else // OLED
    eye[e].display.begin();
#endif
    if(eye[e].blink.pin >= 0) pinMode(eye[e].blink.pin, INPUT_PULLUP);
    digitalWrite(eye[e].cs, HIGH); // Deselect
  }
#ifdef BLINK_PIN
  pinMode(BLINK_PIN, INPUT_PULLUP);
#endif

  // One of the displays is configured to mirror on the X axis.  Simplifies
  // eyelid handling in the drawEye() function -- no need for distinct
  // L-to-R or R-to-L inner loops.  Just the X coordinate of the iris is
  // then reversed when drawing this eye, so they move the same.  Magic!
#ifdef _ADAFRUIT_ST7735H_ // TFT
  digitalWrite(eye[0].cs , LOW);
  digitalWrite(DISPLAY_DC, LOW);
  SPI.transfer(ST7735_MADCTL);
  digitalWrite(DISPLAY_DC, HIGH);
  SPI.transfer(0x88); // MADCTL_MY | MADCTL_BGR
  digitalWrite(eye[0].cs , HIGH);
#else // OLED
  eye[0].display.writeCommand(SSD1351_CMD_SETREMAP);
  eye[0].display.writeData(0x76);
#endif
}


// EYE-RENDERING FUNCTION --------------------------------------------------

SPISettings settings(24000000, MSBFIRST, SPI_MODE3); // Teensy 3.1 max SPI

void drawEye( // Renders one eye.  Inputs must be pre-clipped & valid.
  uint8_t  e,       // Eye array index; 0 or 1 for left/right
  uint32_t iScale,  // Scale factor for iris
  uint8_t  scleraX, // First pixel X offset into sclera image
  uint8_t  scleraY, // First pixel Y offset into sclera image
  uint8_t  uT,      // Upper eyelid threshold value
  uint8_t  lT) {    // Lower eyelid threshold value

  uint8_t  screenX, screenY, scleraXsave;
  int16_t  irisX, irisY;
  uint16_t p, a;
  uint32_t d;

  // Set up raw pixel dump to entire screen.  Although such writes can wrap
  // around automatically from end of rect back to beginning, the region is
  // reset on each frame here in case of an SPI glitch.
  SPI.beginTransaction(settings);
#ifdef _ADAFRUIT_ST7735H_ // TFT
  eye[e].display.setAddrWindow(0, 0, 127, 127);
#else // OLED
  eye[e].display.writeCommand(SSD1351_CMD_SETROW);    // Y range
  eye[e].display.writeData(0); eye[e].display.writeData(SCREEN_HEIGHT - 1);
  eye[e].display.writeCommand(SSD1351_CMD_SETCOLUMN); // X range
  eye[e].display.writeData(0); eye[e].display.writeData(SCREEN_WIDTH  - 1);
  eye[e].display.writeCommand(SSD1351_CMD_WRITERAM);  // Begin write
#endif
  digitalWrite(eye[e].cs, LOW);                       // Chip select
  digitalWrite(DISPLAY_DC, HIGH);                     // Data mode
  // Now just issue raw 16-bit values for every pixel...

  scleraXsave = scleraX; // Save initial X value to reset on each line
  irisY       = scleraY - (SCLERA_HEIGHT - IRIS_HEIGHT) / 2;
  for(screenY=0; screenY<SCREEN_HEIGHT; screenY++, scleraY++, irisY++) {
    scleraX = scleraXsave;
    irisX   = scleraXsave - (SCLERA_WIDTH - IRIS_WIDTH) / 2;
    for(screenX=0; screenX<SCREEN_WIDTH; screenX++, scleraX++, irisX++) {
      if((lower[screenY][screenX] <= lT) ||
         (upper[screenY][screenX] <= uT)) {             // Covered by eyelid
        p = 0;
      } else if((irisY < 0) || (irisY >= IRIS_HEIGHT) ||
                (irisX < 0) || (irisX >= IRIS_WIDTH)) { // In sclera
        p = sclera[scleraY][scleraX];
      } else {                                          // Maybe iris...
        p = polar[irisY][irisX];                        // Polar angle/dist
        d = (iScale * (p & 0x7F)) / 128;                // Distance (Y)
        if(d < IRIS_MAP_HEIGHT) {                       // Within iris area
          a = (IRIS_MAP_WIDTH * (p >> 7)) / 512;        // Angle (X)
          p = iris[d][a];                               // Pixel = iris
        } else {                                        // Not in iris
          p = sclera[scleraY][scleraX];                 // Pixel = sclera
        }
      }
      // SPI FIFO technique from Paul Stoffregen's ILI9341_t3 library:
      while(KINETISK_SPI0.SR & 0xC000); // Wait for space in FIFO
      KINETISK_SPI0.PUSHR = p | SPI_PUSHR_CTAS(1) | SPI_PUSHR_CONT;
    }
  }

  KINETISK_SPI0.SR |= SPI_SR_TCF;         // Clear transfer flag
  while((KINETISK_SPI0.SR & 0xF000) ||    // Wait for SPI FIFO to drain
       !(KINETISK_SPI0.SR & SPI_SR_TCF)); // Wait for last bit out
  digitalWrite(eye[e].cs, HIGH);          // Deselect
  SPI.endTransaction();
}


// EYE ANIMATION -----------------------------------------------------------

const uint8_t ease[] = { // Ease in/out curve for eye movements 3*t^2-2*t^3
    0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  3,   // T
    3,  3,  4,  4,  4,  5,  5,  6,  6,  7,  7,  8,  9,  9, 10, 10,   // h
   11, 12, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23,   // x
   24, 25, 26, 27, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39,   // 2
   40, 41, 42, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 56, 57, 58,   // A
   60, 61, 62, 63, 65, 66, 67, 69, 70, 72, 73, 74, 76, 77, 78, 80,   // l
   81, 83, 84, 85, 87, 88, 90, 91, 93, 94, 96, 97, 98,100,101,103,   // e
  104,106,107,109,110,112,113,115,116,118,119,121,122,124,125,127,   // c
  128,130,131,133,134,136,137,139,140,142,143,145,146,148,149,151,   // J
  152,154,155,157,158,159,161,162,164,165,167,168,170,171,172,174,   // a
  175,177,178,179,181,182,183,185,186,188,189,190,192,193,194,195,   // c
  197,198,199,201,202,203,204,205,207,208,209,210,211,213,214,215,   // o
  216,217,218,219,220,221,222,224,225,226,227,228,228,229,230,231,   // b
  232,233,234,235,236,237,237,238,239,240,240,241,242,243,243,244,   // s
  245,245,246,246,247,248,248,249,249,250,250,251,251,251,252,252,   // o
  252,253,253,253,254,254,254,254,254,255,255,255,255,255,255,255 }; // n

#ifdef AUTOBLINK
uint32_t timeOfLastBlink = 0L, timeToNextBlink = 0L;
#endif

void frame( // Process motion for a single frame of left or right eye
  uint16_t        iScale) {     // Iris scale (0-1023) passed in
  static uint32_t frames   = 0; // Used in frame rate calculation
  static uint8_t  eyeIndex = 0; // eye[] array counter
  int16_t         eyeX, eyeY;
  uint32_t        t = micros(); // Time at start of function

  Serial.println((++frames * 1000) / millis()); // Show frame rate

  if(++eyeIndex >= NUM_EYES) eyeIndex = 0; // Cycle through eyes, 1 per call

  // X/Y movement

#if defined(JOYSTICK_X_PIN) && (JOYSTICK_X_PIN >= 0) && \
    defined(JOYSTICK_Y_PIN) && (JOYSTICK_Y_PIN >= 0)

  // Read X/Y from joystick, constrain to circle
  int16_t dx, dy;
  int32_t d;
  eyeX = analogRead(JOYSTICK_X_PIN); // Raw (unclipped) X/Y reading
  eyeY = analogRead(JOYSTICK_Y_PIN);
#ifdef JOYSTICK_X_FLIP
  eyeX = 1023 - eyeX;
#endif
#ifdef JOYSTICK_Y_FLIP
  eyeY = 1023 - eyeY;
#endif
  dx = (eyeX * 2) - 1023; // A/D exact center is at 511.5.  Scale coords
  dy = (eyeY * 2) - 1023; // X2 so range is -1023 to +1023 w/center at 0.
  if((d = (dx * dx + dy * dy)) > (1023 * 1023)) { // Outside circle
    d    = (int32_t)sqrt((float)d);               // Distance from center
    eyeX = ((dx * 1023 / d) + 1023) / 2;          // Clip to circle edge,
    eyeY = ((dy * 1023 / d) + 1023) / 2;          // scale back to 0-1023
  }

#else // Autonomous X/Y eye motion
      // Periodically initiates motion to a new random point, random speed,
      // holds there for random period until next motion.

  static boolean  eyeInMotion      = false;
  static int16_t  eyeOldX=512, eyeOldY=512, eyeNewX=512, eyeNewY=512;
  static uint32_t eyeMoveStartTime = 0L;
  static int32_t  eyeMoveDuration  = 0L;

  int32_t dt = t - eyeMoveStartTime;      // uS elapsed since last eye event
  if(eyeInMotion) {                       // Currently moving?
    if(dt >= eyeMoveDuration) {           // Time up?  Destination reached.
      eyeInMotion      = false;           // Stop moving
      eyeMoveDuration  = random(3000000); // 0-3 sec stop
      eyeMoveStartTime = t;               // Save initial time of stop
      eyeX = eyeOldX = eyeNewX;           // Save position
      eyeY = eyeOldY = eyeNewY;
    } else { // Move time's not yet fully elapsed -- interpolate position
      int16_t e = ease[255 * dt / eyeMoveDuration] + 1;   // Ease curve
      eyeX = eyeOldX + (((eyeNewX - eyeOldX) * e) / 256); // Interp X
      eyeY = eyeOldY + (((eyeNewY - eyeOldY) * e) / 256); // and Y
    }
  } else {                                // Eye stopped
    eyeX = eyeOldX;
    eyeY = eyeOldY;
    if(dt > eyeMoveDuration) {            // Time up?  Begin new move.
      int16_t  dx, dy;
      uint32_t d;
      do {                                // Pick new dest in circle
        eyeNewX = random(1024);
        eyeNewY = random(1024);
        dx      = (eyeNewX * 2) - 1023;
        dy      = (eyeNewY * 2) - 1023;
      } while((d = (dx * dx + dy * dy)) > (1023 * 1023)); // Keep trying
      eyeMoveDuration  = random(72000, 144000); // ~1/14 - ~1/7 sec
      eyeMoveStartTime = t;               // Save initial time of move
      eyeInMotion      = true;            // Start move on next frame
    }
  }

#endif // JOYSTICK_X_PIN etc.

  // Blinking

#ifdef AUTOBLINK
  // Similar to the autonomous eye movement above -- blink start times
  // and durations are random (within ranges).
  if((t - timeOfLastBlink) >= timeToNextBlink) { // Start new blink?
    timeOfLastBlink = t;
    uint32_t blinkDuration = random(36000, 72000); // ~1/28 - ~1/14 sec
    // Set up durations for both eyes (if not already winking)
    for(uint8_t e=0; e<NUM_EYES; e++) {
      if(eye[e].blink.state == NOBLINK) {
        eye[e].blink.state     = ENBLINK;
        eye[e].blink.startTime = t;
        eye[e].blink.duration  = blinkDuration;
      }
    }
    timeToNextBlink = blinkDuration * 3 + random(4000000);
  }
#endif

  if(eye[eyeIndex].blink.state) { // Eye currently blinking?
    // Check if current blink state time has elapsed
    if((t - eye[eyeIndex].blink.startTime) >= eye[eyeIndex].blink.duration) {
      // Yes -- increment blink state, unless...
      if((eye[eyeIndex].blink.state == ENBLINK) &&  // Enblinking and...
        ((digitalRead(BLINK_PIN) == LOW) ||         // blink or wink held...
          digitalRead(eye[eyeIndex].blink.pin) == LOW)) {
        // Don't advance state yet -- eye is held closed instead
      } else { // No buttons, or other state...
        if(++eye[eyeIndex].blink.state > DEBLINK) { // Deblinking finished?
          eye[eyeIndex].blink.state = NOBLINK;      // No longer blinking
        } else { // Advancing from ENBLINK to DEBLINK mode
          eye[eyeIndex].blink.duration *= 2; // DEBLINK is 1/2 ENBLINK speed
          eye[eyeIndex].blink.startTime = t;
        }
      }
    }
  } else { // Not currently blinking...check buttons!
    if(digitalRead(BLINK_PIN) == LOW) {
      // Manually-initiated blinks have random durations like auto-blink
      uint32_t blinkDuration = random(36000, 72000);
      for(uint8_t e=0; e<NUM_EYES; e++) {
        if(eye[e].blink.state == NOBLINK) {
          eye[e].blink.state     = ENBLINK;
          eye[e].blink.startTime = t;
          eye[e].blink.duration  = blinkDuration;
        }
      }
    } else if(digitalRead(eye[eyeIndex].blink.pin) == LOW) { // Wink!
      eye[eyeIndex].blink.state     = ENBLINK;
      eye[eyeIndex].blink.startTime = t;
      eye[eyeIndex].blink.duration  = random(45000, 90000);
    }
  }

  // Process motion, blinking and iris scale into renderable values

  // Iris scaling: remap from 0-1023 input to iris map height pixel units
  iScale = ((IRIS_MAP_HEIGHT + 1) * 1024) /
           (1024 - (iScale * (IRIS_MAP_HEIGHT - 1) / IRIS_MAP_HEIGHT));

  // Scale eye X/Y positions (0-1023) to pixel units used by drawEye()
  eyeX = map(eyeX, 0, 1023, 0, SCLERA_WIDTH  - 128);
  eyeY = map(eyeY, 0, 1023, 0, SCLERA_HEIGHT - 128);
  if(eyeIndex == 1) eyeX = (SCLERA_WIDTH - 128) - eyeX; // Mirrored display

  // Horizontal position is offset so that eyes are very slightly crossed
  // to appear fixated (converged) at a conversational distance.  Number
  // here was extracted from my posterior and not mathematically based.
  // I suppose one could get all clever with a range sensor, but for now...
  eyeX += 4;
  if(eyeX > (SCLERA_WIDTH - 128)) eyeX = (SCLERA_WIDTH - 128);

  // Eyelids are rendered using a brightness threshold image.  This same
  // map can be used to simplify another problem: making the upper eyelid
  // track the pupil (eyes tend to open only as much as needed -- e.g. look
  // down and the upper eyelid drops).  Just sample a point in the upper
  // lid map slightly above the pupil to determine the rendering threshold.
  static uint8_t uThreshold = 128;
  uint8_t        lThreshold, n;
#ifdef TRACKING
  int16_t sampleX = SCLERA_WIDTH  / 2 - (eyeX / 2), // Reduce X influence
          sampleY = SCLERA_HEIGHT / 2 - (eyeY + IRIS_HEIGHT / 4);
  // Eyelid is slightly asymmetrical, so two readings are taken, averaged
  if(sampleY < 0) n = 0;
  else            n = (upper[sampleY][sampleX] +
                       upper[sampleY][SCREEN_WIDTH - 1 - sampleX]) / 2;
  uThreshold = (uThreshold * 3 + n) / 4; // Filter/soften motion
  // Lower eyelid doesn't track the same way, but seems to be pulled upward
  // by tension from the upper lid.
  lThreshold = 254 - uThreshold;
#else // No tracking -- eyelids full open unless blink modifies them
  uThreshold = lThreshold = 0;
#endif

  // The upper/lower thresholds are then scaled relative to the current
  // blink position so that blinks work together with pupil tracking.
  if(eye[eyeIndex].blink.state) { // Eye currently blinking?
    uint32_t s = (t - eye[eyeIndex].blink.startTime);
    if(s >= eye[eyeIndex].blink.duration) s = 255;   // At or past blink end
    else s = 255 * s / eye[eyeIndex].blink.duration; // Mid-blink
    s          = (eye[eyeIndex].blink.state == DEBLINK) ? 1 + s : 256 - s;
    n          = (uThreshold * s + 254 * (257 - s)) / 256;
    lThreshold = (lThreshold * s + 254 * (257 - s)) / 256;
  } else {
    n          = uThreshold;
  }

  // Pass all the derived values to the eye-rendering function:
  drawEye(eyeIndex, iScale, eyeX, eyeY, n, lThreshold);
}


// AUTONOMOUS IRIS SCALING (if no photocell or dial) -----------------------

#if !defined(IRIS_PIN) || (IRIS_PIN < 0)

// Autonomous iris motion uses a fractal behavior to similate both the major
// reaction of the eye plus the continuous smaller adjustments that occur.

uint16_t oldIris = (IRIS_MIN + IRIS_MAX) / 2, newIris;

void split( // Subdivides motion path into two sub-paths w/randimization
  int16_t  startValue, // Iris scale value (IRIS_MIN to IRIS_MAX) at start
  int16_t  endValue,   // Iris scale value at end
  uint32_t startTime,  // micros() at start
  int32_t  duration,   // Start-to-end time, in microseconds
  int16_t  range) {    // Allowable scale value variance when subdividing

  if(range >= 8) {     // Limit subdvision count, because recursion
    range    /= 2;     // Split range & time in half for subdivision,
    duration /= 2;     // then pick random center point within range:
    int16_t  midValue = (startValue + endValue - range) / 2 + random(range);
    uint32_t midTime  = startTime + duration;
    split(startValue, midValue, startTime, duration, range); // First half
    split(midValue  , endValue, midTime  , duration, range); // Second half
  } else {             // No more subdivisons, do iris motion...
    int32_t dt;        // Time (micros) since start of motion
    int16_t v;         // Interim value
    while((dt = (micros() - startTime)) < duration) {
      v = startValue + (((endValue - startValue) * dt) / duration);
      if(v < IRIS_MIN)      v = IRIS_MIN; // Clip just in case
      else if(v > IRIS_MAX) v = IRIS_MAX;
      frame(v);        // Draw frame w/interim iris scale value
    }
  }
}

#endif // !IRIS_PIN


// MAIN LOOP -- runs continuously after setup() ----------------------------

void loop() {

#ifdef IRIS_PIN && (IRIS_PIN >= 0) // Interactive iris

  uint16_t v = analogRead(IRIS_PIN);       // Raw dial/photocell reading
#ifdef IRIS_PIN_FLIP
  v = 1023 - v;
#endif
  v = map(v, 0, 1023, IRIS_MIN, IRIS_MAX); // Scale to iris range
#ifdef IRIS_SMOOTH // Filter input (gradual motion)
  static uint16_t irisValue = (IRIS_MIN + IRIS_MAX) / 2;
  irisValue = ((irisValue * 15) + v) / 16;
  frame(irisValue);
#else // Unfiltered (immediate motion)
  frame(v);
#endif // IRIS_SMOOTH

#else  // Autonomous iris scaling -- invoke recursive function

  newIris = random(IRIS_MIN, IRIS_MAX);
  split(oldIris, newIris, micros(), 10000000L, IRIS_MAX - IRIS_MIN);
  oldIris = newIris;

#endif // IRIS_PIN
}

User avatar
Bwholt
 
Posts: 5
Joined: Sun Jan 05, 2014 11:46 am

Re: uncanny eyes with Teensy 3.1

Post by Bwholt »

ADDENDUM TO PREVIOUS POST

I have installed all necessary files on another PC and the code still will not compile. I made absolutely sure that I had the latest Adafruit_GFX, Adafruit_ST7735 and SPI libraries. I have no duplicate libraries. I am running the latest version of the Arduino IDE 1.6.5 r5 on both machines. The code will compile with the OLED device engaged in the code. It will not compile with the TFT device engaged in the code. When I say "engaged", I mean I comment or uncomment the appropriate library references on code lines 28 & 29.

I don't know what else I can do here. Two different machines running different versions of Windows (i.e. 7 & 8). Fresh libraries. Unmodified code from the Adafruit website (actually the Github site). There's gotta be something hokey in the as-distributed code or the ST7735 library!

Wayne

User avatar
adafruit_support_mike
 
Posts: 67391
Joined: Thu Feb 11, 2010 2:51 pm

Re: uncanny eyes with Teensy 3.1

Post by adafruit_support_mike »

Okay, I'm able to duplicate the error.

It looks like the ST7735 library uses a data structure that's defined for the Arduino but not for the Teensy. I'll need to check with the developers and see what they suggest.

User avatar
pburgess
 
Posts: 4161
Joined: Sun Oct 26, 2008 2:29 am

Re: uncanny eyes with Teensy 3.1

Post by pburgess »

Please download the latest ST7735 from Github. Install this manually in Documents/Arduino/Libraries, not through the IDE's library manager (it hasn't picked up this changed release yet).

Seems I was building against a version of that library that wasn't yet committed to Github. That should be fixed now, please let me know. Very sorry for the nuisance.

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

Return to “Other Arduino products from Adafruit”