Skip to content

Commit 6e75fac

Browse files
committed
Merge remote-tracking branch 'adafruit/master'
2 parents 535c705 + 9a661b0 commit 6e75fac

5 files changed

Lines changed: 99 additions & 13 deletions

File tree

M4_Eyes/M4_Eyes.ino

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ int iPupilFactor = 42;
5959
uint32_t boopSum = 0;
6060
bool booped = false;
6161
int fixate = 7;
62+
uint8_t lightSensorFailCount = 0;
6263

6364
// For autonomous iris scaling
6465
#define IRIS_LEVELS 7
@@ -191,19 +192,21 @@ void setup() {
191192
eye[e].iris.startAngle = (e & 1) ? 512 : 0; // Rotate alternate eyes 180 degrees
192193
eye[e].iris.angle = eye[e].iris.startAngle;
193194
eye[e].iris.mirror = 0;
194-
eye[e].iris.spin = 0;
195+
eye[e].iris.spin = 0.0;
196+
eye[e].iris.iSpin = 0;
195197
eye[e].sclera.color = 0xFFFF;
196198
eye[e].sclera.data = NULL;
197199
eye[e].sclera.filename = NULL;
198200
eye[e].sclera.startAngle = (e & 1) ? 512 : 0; // Rotate alternate eyes 180 degrees
199201
eye[e].sclera.angle = eye[e].sclera.startAngle;
200202
eye[e].sclera.mirror = 0;
201-
eye[e].sclera.spin = 0;
203+
eye[e].sclera.spin = 0.0;
204+
eye[e].sclera.iSpin = 0;
202205

203206
// Uncanny eyes carryover stuff for now, all messy:
204207
eye[e].blink.state = NOBLINK;
205-
eye[e].eyeX = 512;
206-
eye[e].eyeY = 512;
208+
// eye[e].eyeX = 512;
209+
// eye[e].eyeY = 512;
207210
eye[e].blinkFactor = 0.0;
208211
}
209212

@@ -328,6 +331,12 @@ void setup() {
328331
Serial.printf("Free RAM: %d\n", availableRAM());
329332

330333
randomSeed(SysTick->VAL + analogRead(A2));
334+
eyeOldX = eyeNewX = eyeOldY = eyeNewY = mapRadius; // Start in center
335+
for(e=0; e<NUM_EYES; e++) { // For each eye...
336+
eye[e].eyeX = eyeOldX;
337+
eye[e].eyeY = eyeOldY;
338+
}
339+
lastLightReadTime = micros() + 2000000; // Delay initial light reading
331340
}
332341

333342
// LOOP FUNCTION - CALLED REPEATEDLY UNTIL POWER-OFF -----------------------
@@ -429,12 +438,21 @@ void loop() {
429438
// both eyes. This comment has nothing to do with the code.
430439
uint16_t rawReading = (lightSensorPin >= 100) ?
431440
seesaw.analogRead(lightSensorPin - 100) : analogRead(lightSensorPin);
432-
if(rawReading < lightSensorMin) rawReading = lightSensorMin; // Clamp light sensor range
433-
else if(rawReading > lightSensorMax) rawReading = lightSensorMax; // to within usable range
434-
float v = (float)(rawReading - lightSensorMin) / (float)(lightSensorMax - lightSensorMin); // 0.0 to 1.0
435-
v = pow(v, lightSensorCurve);
436-
lastLightValue = irisMin + v * irisRange;
437-
lastLightReadTime = t;
441+
if(rawReading <= 1023) {
442+
if(rawReading < lightSensorMin) rawReading = lightSensorMin; // Clamp light sensor range
443+
else if(rawReading > lightSensorMax) rawReading = lightSensorMax; // to within usable range
444+
float v = (float)(rawReading - lightSensorMin) / (float)(lightSensorMax - lightSensorMin); // 0.0 to 1.0
445+
v = pow(v, lightSensorCurve);
446+
lastLightValue = irisMin + v * irisRange;
447+
lastLightReadTime = t;
448+
lightSensorFailCount = 0;
449+
} else { // I2C error
450+
if(++lightSensorFailCount >= 50) { // If repeated errors in succession...
451+
lightSensorPin = -1; // Stop trying to use the light sensor
452+
} else {
453+
lastLightReadTime = t - LIGHT_INTERVAL + 40000; // Try again in 40 ms
454+
}
455+
}
438456
}
439457
irisValue = (irisValue * 0.97) + (lastLightValue * 0.03); // Filter response for smooth reaction
440458
} else {
@@ -556,8 +574,18 @@ void loop() {
556574
}
557575

558576
float mins = (float)millis() / 60000.0;
559-
eye[eyeNum].iris.angle = (int)((float)eye[eyeNum].iris.startAngle + eye[eyeNum].iris.spin * mins + 0.5);
560-
eye[eyeNum].sclera.angle = (int)((float)eye[eyeNum].sclera.startAngle + eye[eyeNum].sclera.spin * mins + 0.5);
577+
if(eye[eyeNum].iris.iSpin) {
578+
// Spin works in fixed amount per frame (eyes may lose sync, but "wagon wheel" tricks work)
579+
eye[eyeNum].iris.angle += eye[eyeNum].iris.iSpin;
580+
} else {
581+
// Keep consistent timing in spin animation (eyes stay in sync, no "wagon wheel" effects)
582+
eye[eyeNum].iris.angle = (int)((float)eye[eyeNum].iris.startAngle + eye[eyeNum].iris.spin * mins + 0.5);
583+
}
584+
if(eye[eyeNum].sclera.iSpin) {
585+
eye[eyeNum].sclera.angle += eye[eyeNum].sclera.iSpin;
586+
} else {
587+
eye[eyeNum].sclera.angle = (int)((float)eye[eyeNum].sclera.startAngle + eye[eyeNum].sclera.spin * mins + 0.5);
588+
}
561589

562590
// END ONCE-PER-FRAME EYE ANIMATION ----------------------------------
563591

M4_Eyes/file.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,9 @@ void loadConfig(char *filename) {
257257
irisMirror = 0,
258258
scleraMirror = 0,
259259
irisAngle = 0,
260-
scleraAngle = 0;
260+
scleraAngle = 0,
261+
irisiSpin = 0,
262+
scleraiSpin = 0;
261263
float irisSpin = 0.0,
262264
scleraSpin = 0.0;
263265
JsonVariant iristv = doc["irisTexture"],
@@ -268,6 +270,10 @@ void loadConfig(char *filename) {
268270
if(v.is<float>()) irisSpin = v.as<float>() * -1024.0;
269271
v = doc["scleraSpin"];
270272
if(v.is<float>()) scleraSpin = v.as<float>() * -1024.0;
273+
v = doc["irisiSpin"];
274+
if(v.is<int>()) irisiSpin = v.as<int>();
275+
v = doc["scleraiSpin"];
276+
if(v.is<int>()) scleraiSpin = v.as<int>();
271277
v = doc["irisMirror"];
272278
if(v.is<bool>() || v.is<int>()) irisMirror = v ? 1023 : 0;
273279
v = doc["scleraMirror"];
@@ -294,6 +300,8 @@ void loadConfig(char *filename) {
294300
eye[e].sclera.mirror = scleraMirror;
295301
eye[e].iris.spin = irisSpin;
296302
eye[e].sclera.spin = scleraSpin;
303+
eye[e].iris.iSpin = irisiSpin;
304+
eye[e].sclera.iSpin = scleraiSpin;
297305
// iris and sclera filenames are strdup'd for each eye rather than
298306
// sharing a common pointer, reason being that it gets really messy
299307
// below when overriding one or the other and trying to do the right
@@ -325,6 +333,10 @@ void loadConfig(char *filename) {
325333
if(v.is<float>()) eye[e].iris.spin = v.as<float>() * -1024.0;
326334
v = doc[eye[e].name]["scleraSpin"];
327335
if(v.is<float>()) eye[e].sclera.spin = v.as<float>() * -1024.0;
336+
v = doc[eye[e].name]["irisiSpin"];
337+
if(v.is<int>()) eye[e].iris.iSpin = v.as<int>();
338+
v = doc[eye[e].name]["scleraiSpin"];
339+
if(v.is<int>()) eye[e].sclera.iSpin = v.as<int>();
328340
v = doc[eye[e].name]["irisMirror"];
329341
if(v.is<bool>() || v.is<int>()) eye[e].iris.mirror = v ? 1023 : 0;
330342
v = doc[eye[e].name]["scleraMirror"];

M4_Eyes/globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ typedef struct {
131131
uint16_t startAngle; // INITIAL rotation 0-1023 CCW
132132
uint16_t angle; // CURRENT rotation 0-1023 CCW
133133
uint16_t mirror; // 0 = normal, 1023 = flip X axis
134+
uint16_t iSpin; // Per-frame fixed integer spin, overrides 'spin' value
134135
} texture;
135136

136137
// Each eye then uses the following structure. Each eye must be on its own

Pylint_and_CircuitPython/.circuitpython.skip

Whitespace-only changes.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import board
2+
import digitalio
3+
import adafruit_lis3dh
4+
import touchio
5+
import time
6+
import neopixel
7+
import adafruit_thermistor
8+
9+
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2)
10+
11+
i2c = board.I2C()
12+
int1 = digitalio.DigitalInOut(board.ACCELEROMETER_UNTERRUPT)
13+
lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c, int1=int1)
14+
15+
circuit_playground_temperature = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950)
16+
17+
touch_A1 = touchio.TouchIn(board.A1)
18+
touch_A2 = touchio.TouchIn(board.A2)
19+
20+
led = digitalio.DigitalInOut(board.D13)
21+
led.direction = digitalio.Direction.OUTPUT
22+
23+
button_A = digitalio.DigitalInOut(board.BUTTON_A)
24+
button_A.direction = digitalio.Direction.INPUT
25+
button_A.pull = digitalio.Pull.DOWN
26+
27+
while True:
28+
x, y, z = lis3dh.acceleration
29+
30+
if button_A.value:
31+
led.value = True
32+
else:
33+
led.value = False
34+
35+
print("Temperature:", circuit_playground_temperature.temperature)
36+
print("Acceleration:", x, y, z)
37+
38+
if touch_A1.value:
39+
pixels.fill((255, 0, 0))
40+
if touch_A2.value:
41+
pixels.fill((0, 0, 255))
42+
else:
43+
pixels.fill((0, 0, 0))
44+
45+
time.sleep(0.01)

0 commit comments

Comments
 (0)