Merge remote-tracking branch 'adafruit/master'

This commit is contained in:
Dave Astels 2019-08-23 13:38:41 -04:00
commit 6e75facefd
5 changed files with 99 additions and 13 deletions

View file

@ -59,6 +59,7 @@ int iPupilFactor = 42;
uint32_t boopSum = 0;
bool booped = false;
int fixate = 7;
uint8_t lightSensorFailCount = 0;
// For autonomous iris scaling
#define IRIS_LEVELS 7
@ -191,19 +192,21 @@ void setup() {
eye[e].iris.startAngle = (e & 1) ? 512 : 0; // Rotate alternate eyes 180 degrees
eye[e].iris.angle = eye[e].iris.startAngle;
eye[e].iris.mirror = 0;
eye[e].iris.spin = 0;
eye[e].iris.spin = 0.0;
eye[e].iris.iSpin = 0;
eye[e].sclera.color = 0xFFFF;
eye[e].sclera.data = NULL;
eye[e].sclera.filename = NULL;
eye[e].sclera.startAngle = (e & 1) ? 512 : 0; // Rotate alternate eyes 180 degrees
eye[e].sclera.angle = eye[e].sclera.startAngle;
eye[e].sclera.mirror = 0;
eye[e].sclera.spin = 0;
eye[e].sclera.spin = 0.0;
eye[e].sclera.iSpin = 0;
// Uncanny eyes carryover stuff for now, all messy:
eye[e].blink.state = NOBLINK;
eye[e].eyeX = 512;
eye[e].eyeY = 512;
// eye[e].eyeX = 512;
// eye[e].eyeY = 512;
eye[e].blinkFactor = 0.0;
}
@ -328,6 +331,12 @@ void setup() {
Serial.printf("Free RAM: %d\n", availableRAM());
randomSeed(SysTick->VAL + analogRead(A2));
eyeOldX = eyeNewX = eyeOldY = eyeNewY = mapRadius; // Start in center
for(e=0; e<NUM_EYES; e++) { // For each eye...
eye[e].eyeX = eyeOldX;
eye[e].eyeY = eyeOldY;
}
lastLightReadTime = micros() + 2000000; // Delay initial light reading
}
// LOOP FUNCTION - CALLED REPEATEDLY UNTIL POWER-OFF -----------------------
@ -429,12 +438,21 @@ void loop() {
// both eyes. This comment has nothing to do with the code.
uint16_t rawReading = (lightSensorPin >= 100) ?
seesaw.analogRead(lightSensorPin - 100) : analogRead(lightSensorPin);
if(rawReading < lightSensorMin) rawReading = lightSensorMin; // Clamp light sensor range
else if(rawReading > lightSensorMax) rawReading = lightSensorMax; // to within usable range
float v = (float)(rawReading - lightSensorMin) / (float)(lightSensorMax - lightSensorMin); // 0.0 to 1.0
v = pow(v, lightSensorCurve);
lastLightValue = irisMin + v * irisRange;
lastLightReadTime = t;
if(rawReading <= 1023) {
if(rawReading < lightSensorMin) rawReading = lightSensorMin; // Clamp light sensor range
else if(rawReading > lightSensorMax) rawReading = lightSensorMax; // to within usable range
float v = (float)(rawReading - lightSensorMin) / (float)(lightSensorMax - lightSensorMin); // 0.0 to 1.0
v = pow(v, lightSensorCurve);
lastLightValue = irisMin + v * irisRange;
lastLightReadTime = t;
lightSensorFailCount = 0;
} else { // I2C error
if(++lightSensorFailCount >= 50) { // If repeated errors in succession...
lightSensorPin = -1; // Stop trying to use the light sensor
} else {
lastLightReadTime = t - LIGHT_INTERVAL + 40000; // Try again in 40 ms
}
}
}
irisValue = (irisValue * 0.97) + (lastLightValue * 0.03); // Filter response for smooth reaction
} else {
@ -556,8 +574,18 @@ void loop() {
}
float mins = (float)millis() / 60000.0;
eye[eyeNum].iris.angle = (int)((float)eye[eyeNum].iris.startAngle + eye[eyeNum].iris.spin * mins + 0.5);
eye[eyeNum].sclera.angle = (int)((float)eye[eyeNum].sclera.startAngle + eye[eyeNum].sclera.spin * mins + 0.5);
if(eye[eyeNum].iris.iSpin) {
// Spin works in fixed amount per frame (eyes may lose sync, but "wagon wheel" tricks work)
eye[eyeNum].iris.angle += eye[eyeNum].iris.iSpin;
} else {
// Keep consistent timing in spin animation (eyes stay in sync, no "wagon wheel" effects)
eye[eyeNum].iris.angle = (int)((float)eye[eyeNum].iris.startAngle + eye[eyeNum].iris.spin * mins + 0.5);
}
if(eye[eyeNum].sclera.iSpin) {
eye[eyeNum].sclera.angle += eye[eyeNum].sclera.iSpin;
} else {
eye[eyeNum].sclera.angle = (int)((float)eye[eyeNum].sclera.startAngle + eye[eyeNum].sclera.spin * mins + 0.5);
}
// END ONCE-PER-FRAME EYE ANIMATION ----------------------------------

View file

@ -257,7 +257,9 @@ void loadConfig(char *filename) {
irisMirror = 0,
scleraMirror = 0,
irisAngle = 0,
scleraAngle = 0;
scleraAngle = 0,
irisiSpin = 0,
scleraiSpin = 0;
float irisSpin = 0.0,
scleraSpin = 0.0;
JsonVariant iristv = doc["irisTexture"],
@ -268,6 +270,10 @@ void loadConfig(char *filename) {
if(v.is<float>()) irisSpin = v.as<float>() * -1024.0;
v = doc["scleraSpin"];
if(v.is<float>()) scleraSpin = v.as<float>() * -1024.0;
v = doc["irisiSpin"];
if(v.is<int>()) irisiSpin = v.as<int>();
v = doc["scleraiSpin"];
if(v.is<int>()) scleraiSpin = v.as<int>();
v = doc["irisMirror"];
if(v.is<bool>() || v.is<int>()) irisMirror = v ? 1023 : 0;
v = doc["scleraMirror"];
@ -294,6 +300,8 @@ void loadConfig(char *filename) {
eye[e].sclera.mirror = scleraMirror;
eye[e].iris.spin = irisSpin;
eye[e].sclera.spin = scleraSpin;
eye[e].iris.iSpin = irisiSpin;
eye[e].sclera.iSpin = scleraiSpin;
// iris and sclera filenames are strdup'd for each eye rather than
// sharing a common pointer, reason being that it gets really messy
// below when overriding one or the other and trying to do the right
@ -325,6 +333,10 @@ void loadConfig(char *filename) {
if(v.is<float>()) eye[e].iris.spin = v.as<float>() * -1024.0;
v = doc[eye[e].name]["scleraSpin"];
if(v.is<float>()) eye[e].sclera.spin = v.as<float>() * -1024.0;
v = doc[eye[e].name]["irisiSpin"];
if(v.is<int>()) eye[e].iris.iSpin = v.as<int>();
v = doc[eye[e].name]["scleraiSpin"];
if(v.is<int>()) eye[e].sclera.iSpin = v.as<int>();
v = doc[eye[e].name]["irisMirror"];
if(v.is<bool>() || v.is<int>()) eye[e].iris.mirror = v ? 1023 : 0;
v = doc[eye[e].name]["scleraMirror"];

View file

@ -131,6 +131,7 @@ typedef struct {
uint16_t startAngle; // INITIAL rotation 0-1023 CCW
uint16_t angle; // CURRENT rotation 0-1023 CCW
uint16_t mirror; // 0 = normal, 1023 = flip X axis
uint16_t iSpin; // Per-frame fixed integer spin, overrides 'spin' value
} texture;
// Each eye then uses the following structure. Each eye must be on its own

View file

@ -0,0 +1,45 @@
import board
import digitalio
import adafruit_lis3dh
import touchio
import time
import neopixel
import adafruit_thermistor
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2)
i2c = board.I2C()
int1 = digitalio.DigitalInOut(board.ACCELEROMETER_UNTERRUPT)
lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c, int1=int1)
circuit_playground_temperature = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950)
touch_A1 = touchio.TouchIn(board.A1)
touch_A2 = touchio.TouchIn(board.A2)
led = digitalio.DigitalInOut(board.D13)
led.direction = digitalio.Direction.OUTPUT
button_A = digitalio.DigitalInOut(board.BUTTON_A)
button_A.direction = digitalio.Direction.INPUT
button_A.pull = digitalio.Pull.DOWN
while True:
x, y, z = lis3dh.acceleration
if button_A.value:
led.value = True
else:
led.value = False
print("Temperature:", circuit_playground_temperature.temperature)
print("Acceleration:", x, y, z)
if touch_A1.value:
pixels.fill((255, 0, 0))
if touch_A2.value:
pixels.fill((0, 0, 255))
else:
pixels.fill((0, 0, 0))
time.sleep(0.01)