Last active
August 29, 2015 14:00
-
-
Save alexglow/030777f939f58b3a987c to your computer and use it in GitHub Desktop.
Sally and I are building a little weather display for Pinoccio Tryday! Here are my notes along the way.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
To find the limits on a new servo ("testing testing"): | |
function tt { timer3.pwm(3, arg(1)); }; | |
tt(whatever) | |
Black micro-servo: 40 / 120 | |
Blue micro-servo: 30 / 115 (it seems to turn backwards from the black one?) | |
Black HS-311: 30 / 125 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Temperature controls LED | |
2. Temperature *also* controls servo | |
3. Weather thingy controls servo | |
FIRST SHOT, EASY MODE: TEMPERATURE | |
f = (9*temperature)/5 + 32 | |
print f | |
led = 0-255 | |
(9*t)/5 + 32 | |
Let's use Fahrenheit and display 0-100 (approximate human-livable conditions) as LED values. | |
tempred = 2.55*f | |
Actually, fade from blue to white to yellow to red. | |
-30 to 0 = blue to white | |
0 to 60 = white to yellow | |
60 to 110 = yellow to red | |
YOU KNOW WHAT I SHOULD NOT BE SINKING TIME INTO THIS BIT. | |
Let's just enter values directly - Sally has five weather states: | |
0. Snow | |
1. Rain | |
2. Cloudy | |
3. Partly cloudy | |
4. Clear & sunny | |
So, let's do: value "w". | |
Servo goes 0 - 180? | |
Let's abstract it, so that we can use different servo limits. | |
Servo lower limit = l | |
Servo max = h | |
Servo range = r | |
Number of weather options = o | |
Increment per weather option = i | |
Current weather state (per numbered list above) = w | |
Servo position = p | |
r = h - l // the servo's range is a positive number | |
i = r/o // the servo moves in increments determined by the range divided by the number of possible states | |
p = iw + l // the servo position is set by starting from the lower limit and adding the number of increments corresponding to the current weather state |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I'm working from https://github.com/jacobrosenthal/TimerThree/blob/master/examples/Pinoccio/Pinoccio.ino | |
...and not such a hotshot at Arduino. So let's brute-force it! Try uploading the sketch and see what happens. | |
First, errors finding version.h . So, I drill into the hardware-pinoccio repo and find a version.h, and add it via Sketch > Add File. That fixes that error, and now it's complaining about all the variables I didn't fill out. So, save this as a new sketch, reopen the original one next to it, and try subbing things in... | |
***** | |
Build options changed, rebuilding all | |
In file included from PinoccioServo.ino:26:0: | |
/Users/alex/Documents/Arduino/libraries/TimerThree/TimerThree.h: In member function 'void TimerThree::setPwmDuty(char, unsigned int)': | |
/Users/alex/Documents/Arduino/libraries/TimerThree/TimerThree.h:102:13: error: 'TIMER3_A_PIN' was not declared in this scope | |
if (pin == TIMER3_A_PIN) OCR3A = dutyCycle; | |
^ | |
/Users/alex/Documents/Arduino/libraries/TimerThree/TimerThree.h: In member function 'void TimerThree::pwm(char, unsigned int)': | |
/Users/alex/Documents/Arduino/libraries/TimerThree/TimerThree.h:111:13: error: 'TIMER3_A_PIN' was not declared in this scope | |
if (pin == TIMER3_A_PIN) { pinMode(TIMER3_A_PIN, OUTPUT); TCCR3A |= _BV(COM3A1); } | |
^ | |
/Users/alex/Documents/Arduino/libraries/TimerThree/TimerThree.h: In member function 'void TimerThree::disablePwm(char)': | |
/Users/alex/Documents/Arduino/libraries/TimerThree/TimerThree.h:126:13: error: 'TIMER3_A_PIN' was not declared in this scope | |
if (pin == TIMER3_A_PIN) TCCR3A &= ~_BV(COM3A1); | |
^ | |
PinoccioServo.ino: In function 'void setup()': | |
PinoccioServo.ino:49:15: error: 'SKETCH_NAME' was not declared in this scope | |
PinoccioServo.ino:49:28: error: 'SKETCH_REVISION' was not declared in this scope | |
PinoccioServo.ino:49:45: error: 'SKETCH_BUILD' was not declared in this scope | |
***** | |
Here we abandon coding and work on the hardware bit, until Eric comes back and we can pester him for code samples from his awesome little tri-servo tumbler robot. | |
***** | |
ERIC SAYS | |
so if you grab the timerthree lib from that Github url, put it in your Documents/Arduino/libraries folder, then restart the IDE | |
if it's installed correctly, you should see this: File > Examples > TimerThree > Pinoccio | |
Choose the "Pinoccio" one | |
Then, you just do this: | |
function startup { timer3.initialize(20000); }; | |
function left { timer3.pwm(5, arg(1)); }; | |
function center { timer3.pwm(4, arg(1)); }; | |
function right { timer3.pwm(3, arg(1)); }; | |
function centerleft { center(56) }; | |
function centerright { center(68) }; | |
function centercenter { center(62) }; | |
function rightforward { right(72) }; | |
function rightbackward { right(52) }; | |
function rightcenter { right(64) }; | |
function leftforward { left(52) }; | |
function leftbackward { left(72) }; | |
function leftcenter { left(62) }; | |
function centerall { centercenter; leftcenter; rightcenter }; | |
function leftgait { centerleft; leftforward; rightbackward; }; | |
function rightgait { centerright; rightforward; leftbackward }; | |
well, "just do this" is my code for the little servo walker | |
the only one that matters is startup, to initialize the timer | |
then to, say, move a servo connected to pin 5, you would do `timer3.pwm(5, 70)` or `timer3.pwm(5, 90)` | |
my little servos go between I think 20 and 150 or so | |
80 is right about center | |
not sure if that's typical of all servos, but that should do it? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Now, I get an error: | |
Pinoccio.ino: In function 'void setup()': | |
Pinoccio.ino:49:57: error: no matching function for call to 'PinoccioScout::setup(const char [7], const char [8], int)' | |
Pinoccio.ino:49:57: note: candidate is: | |
In file included from Pinoccio.ino:30:0: | |
/Users/alex/Documents/Arduino/libraries/pinoccio/src/Scout.h:39:10: note: void PinoccioScout::setup() | |
void setup(); | |
^ | |
/Users/alex/Documents/Arduino/libraries/pinoccio/src/Scout.h:39:10: note: candidate expects 0 arguments, 3 provided | |
Changed line 49 to: | |
Scout.setup(); | |
AND IT UPLOADS! Flashes the torch color rapidly, for under a minute. | |
-- | |
So, I entered: | |
Hello from Pinoccio! | |
(Shell based on Bitlash v2.0 (c) 2014 Bill Roy) | |
18198 bytes free | |
Build 2014040301 | |
Lead Scout ready | |
> function startup { timer3.initialize(20000); }; | |
saved | |
> timer3.initialize(20000); | |
> function dial { timer3.pwm(3,p); }; | |
saved | |
> p = 40 | |
> dial | |
> p = 80 | |
> dial | |
> | |
MOVEMENT!!!! | |
function right { timer3.pwm(3, arg(1)); }; | |
right(20) | |
rm right | |
function pos { timer3.pwm(3, arg(1)); }; | |
***** | |
start to write a function to increment down and find the place where it stops: will step down 1º at a time and print its position, and I'll note where it freezes. | |
based on this LED fader: | |
while (a > 0) { | |
led.setrgb(0, a, 0); | |
a--; | |
} | |
I start... | |
function countdown { | |
while (a > 0) { | |
} | |
} | |
but then, too time-consuming; decide to just test some numbers. | |
> pos(25) | |
> pos(30) | |
> pos(40) | |
> pos(35) | |
> pos(30) | |
It makes little upset whirring noises when it tries to go past its limits. | |
> pos(36) | |
> pos(40) | |
l = 40 | |
90º from there appears to be about 86-8; call it 87. (47 ticks) (1.85º per tick) | |
> pos(50) | |
> pos(60) | |
> pos(70) | |
> pos(80) | |
> pos(90) | |
> pos(87) | |
> pos(86) | |
> pos(87) | |
> pos(88) | |
> pos(100) | |
> pos(110) | |
> pos(120) | |
> pos(130) | |
> pos(125) | |
> pos(120) | |
h = 120 | |
which is about 140º off from where we started. | |
80 ticks, 140º ish... does that match up? That's about 1.75º/tick. Then again, I'm just kinda eyeballing the angle. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Revisiting... | |
> function startup { timer3.initialize(20000); }; | |
saved | |
> timer3.initialize(20000); | |
> function dial { timer3.pwm(3,p); }; | |
saved | |
> p = 40 | |
> dial | |
so, I want a function to move the servo to p for a given weather station. | |
From scratch, it would be: | |
function pos { p = (i*w) + l; print p; timer3.pwm(3,p); }; | |
function startup { timer3.initialize(20000); l = 40; i = 16; w = 0; pos; }; | |
timer3.initialize(20000); | |
run pos,3600000 | |
• I need to re-pull p every time I used it, so that it would get the newest w value. That means putting the definition of "p" inside pos. | |
• I need to run pos to set the position every time it turns on. That means calling it inside the startup function. | |
• I need to poll for new weather conditions. Once an hour should be sufficient. 1000 ms/sec * 60 sec/min * 60 min/hour = 3600000 ms. | |
Test it thus: | |
run pos,1000 | |
then change values of w (0-4). (Ooh! I've got a clock!) | |
OH! I have an extra increment! That's right: since we're using the two extremes, that means that only the middle three act as "dividers". So, i should actually be determined with (w-1). So, i should actually be 20 ticks. | |
function startup { timer3.initialize(20000); l = 40; i = 20; w = 0; pos; }; | |
So: | |
function pos { p = (i*w) + l; print p; timer3.pwm(3,p); }; | |
function startup { timer3.initialize(20000); l = 40; i = 20; w = 0; pos; }; | |
timer3.initialize(20000); | |
run pos,3600000 | |
Since I've abstracted the values, though, as soon as I enter the correct value for i (20), the servo corrects itself! | |
Cooliooooo! This now does exactly what I want it to! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sally has drawn a weather dial with five states: | |
0. Snow | |
1. Rain | |
2. Cloudy | |
3. Partly cloudy | |
4. Clear & sunny | |
Here are the variables I'm working with: | |
CONFIG (fairly static) | |
l = servo lower limit = 40 | |
h = servo max limit = 120 | |
o = number of weather options = 5 | |
CALCULATED FROM CONFIG (equally static) | |
r = servo range = h-l = 80 | |
i = increment per weather option = r / (o-1) = 20 | |
MODIFIED WHILE RUNNING | |
w = current weather state (per numbered list above) | |
p = servo position = iw + l | |
ALL THE FORMULAS (FORMULAE) AGAIN | |
r = h - l // the servo's range is a positive number | |
i = r/o // the servo moves in increments determined by the range divided by the number of possible states | |
p = iw + l // the servo position is set by starting from the lower limit and adding the number of increments corresponding to the current weather state | |
If you know all of the CONFIG values, you can simply plug in l and i, plus a starting value for w (0) and the function for p. If you're going to be plugging in different servos (or changing dials), you might want to leave them as formulas and edit the startup function whenever you switch something out, then reboot the Scout. | |
FINAL SET OF THINGS THAT GO ON THE SCOUT | |
function pos { p = (i*w) + l; print p; timer3.pwm(3,p); }; | |
function startup { timer3.initialize(20000); l = 40; i = 20; w = 0; pos; }; | |
timer3.initialize(20000); | |
run pos,3600000 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note the difference between lower-case L and one. Could probably have gone with a better choice for GitHub's sake, but TextMate differentiates them just fine :)