I tested it on my ATtiny 84 and 85, but I just have a cheap analog micro servo so it would be good to get more testers. Also I don't have a 2313 so it would be nice to see if it works there too.
The library consumes roughly 750 bytes of flash and (I think) 10 bytes of RAM. This is nearly half the flash required by SoftwareServo, and unlike SoftwareServo, needs no (indeed, has no) refresh() function in loop().
On ATTiny85, you can run at 8MHz or 16MHz, but for 8MHz it's recommended (but not required) that you edit /hardware/arduino/cores/tiny/core_build_options.h and move the Core to Timer0.
Disclaimer: Servo damage may occur! The library will send 600uS to 2400uS pulses which may be beyond the physical reach of some servos, so use with care.
When trying to compile the example (using Arduino IDE 1.0.5) with ATtiny85 @ 8Mhz setting I get errors:
In file included from TinyServo.cpp:7:
/TinyServo.h:77:4: error: #error TinyServo library does not support this processor.
TinyServo.cpp: In function 'void moveServo(byte, byte)':
TinyServo.cpp:25: error: 'SERVOMAX' was not declared in this scope
TinyServo.cpp: In function 'void setupServos()':
TinyServo.cpp:64: error: 'OCRxA' was not declared in this scope
TinyServo.cpp: At global scope:
TinyServo.cpp:97: error: expected unqualified-id before 'if'
TinyServo.cpp:104: error: expected unqualified-id before 'else'
From the pre-processor DEFINE statements, it is obvious you were targeting to support ATtiny85 chips. I am not an expert on pre-processor statements, but am thinking I need to predefine some statement. Can someone help me resolve these errors?
I had the .h/.cpp files in same folder as the example sketch. I did not modify any of the files.
I have tried having the files in the TinyServo folder under Libraries [..\Arduino\libraries\TinyServo]. Compiling the Example in the examples folder [..\Arduino\libraries\TinyServo\examples\TinyServoExample\TinyServoExample.ino] still did not compile. Get same compiler error.
In file included from TinyServoExample.ino:39:
C:\Users\Krist\Documents\Arduino\libraries\TinyServo/TinyServo.h:77:4: error: #error TinyServo library does not support this processor.
TinyServoExample.ino: In function 'void loop()':
TinyServoExample:97: error: 'SERVOMAX' was not declared in this scope
Not sure why. I have used other user built libraries and examples without trouble. I am not seeing anything obvious in the code, and obviously others have the library working.
thank you...let me try this. I was using cores I got from http://hlt.media.mit.edu/?p=1229. Had boards.txt that included the below...I used "attiny85-8.name=ATtiny85 (internal 8 MHz clock)". I will try using this other hardware core you suggest. I am assuming I just load those files into the "Hardware" folder like I did for the other cores.
perfect feedback...thank you. I used new core files for Arduino 1.0, put them in Hardware folder, and changed the "Prospective Boards.txt" file to just "boards.txt". Servo is running as expected with example code! Thank you very much!
The servo performance is better [smoother] than the library I was using before.
I will play with this library more and provide whatever feedback I can.
question before I get into my beta testing. For power conservation reasons, I am going to putting my ATtiny85 into extended sleep modes. I will be putting into the cyclic sleep using the watchdog timer [setup_watchdog(WDTO_8S)] and repeatedly wake/sleep for a specified number of cycles and then enabling servo commands (along with some other activity). Are you already aware of issues that may arise from using your library under these conditions because of how you are using the timers?
If I run into any anomalies, I will share them in this forum.
Well glad you got it working. I'm not familiar with the HLT core but I assume the constants for CPU definition are different or don't exist.
As for sleeping, I haven't tested that but I since interrupts are disabled when sleeping, one of the servo pins would get left in a HIGH state when sleeping which may send the servo to the extreme end of travel. To sleep safely, I would recommend something like the following sequence. Whether you need to disable/enable Timer0 or Timer1 depends on if you have moved millis(). The below example assumes TinyServo is using Timer1, substitute OCIE0A for OCIE1A if TinyServo is using Timer0.
TIMSK &= ~(1 << OCIE1A); // Disable Timer/Counter1 Output Compare Match A Interrupt, preserving other bits
digitalWrite(servoPin[currentServo], LOW);
// sleep here
TIMSK |= (1 << OCIE1A); // Timer/Counter1 Output Compare Match A Interrupt Enable, preserving other bits
I'm not certain this will work but it's a good place to start. I suppose I should upgrade the library to add a "detach servo" function for situations like this. So, thanks for the feedback, you found a use case I missed.
I tried it and with ATtiny2313 @ 8 MHz, with the following boards.txt code
attiny2313at8.name=ATtiny2313 @ 8 MHz
# The following do NOT work...
# attiny2313at8.upload.using=avrispv2
# attiny2313at8.upload.using=Pololu USB AVR Programmer
# The following DO work (pick one)...
attiny2313at8.upload.using=arduino:arduinoisp
# attiny2313at8.upload.protocol=avrispv2
# attiny2313at8.upload.using=pololu
attiny2313at8.upload.maximum_size=2048
# Default clock (slowly rising power; long delay to clock; 8 MHz internal)
# Int. RC Osc. 8 MHz; Start-up time: 14 CK + 65 ms; [CKSEL=0100 SUT=10]; default value
# Brown-out detection disabled; [BODLEVEL=111]
# Serial program downloading (SPI) enabled; [SPIEN=0]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]
attiny2313at8.bootloader.low_fuses=0xE4
attiny2313at8.bootloader.high_fuses=0x9F
attiny2313at8.bootloader.extended_fuses=0xFF
attiny2313at8.bootloader.path=empty
attiny2313at8.bootloader.file=empty2313at8.hex
attiny2313at8.build.mcu=attiny2313
attiny2313at8.build.f_cpu=8000000L
attiny2313at8.build.core=tiny
the example code compiles ok (haven't tested it on the core itself) but if I select ATtiny2313 @ 1 MHz (with this code):
attiny2313at1.name=ATtiny2313 @ 1 MHz
# The following do NOT work...
# attiny2313at1.upload.using=avrispv2
# attiny2313at1.upload.using=Pololu USB AVR Programmer
# The following DO work (pick one)...
attiny2313at1.upload.using=arduino:arduinoisp
# attiny2313at1.upload.protocol=avrispv2
# attiny2313at1.upload.using=pololu
attiny2313at1.upload.maximum_size=2048
# Default clock (slowly rising power; long delay to clock; 8 MHz internal; divide clock by 8)
# Int. RC Osc. 8 MHz; Start-up time: 14 CK + 65 ms; [CKSEL=0100 SUT=10]; default value
# Divide clock by 8 internally; [CKDIV8=0]
# Brown-out detection disabled; [BODLEVEL=111]
# Serial program downloading (SPI) enabled; [SPIEN=0]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]
attiny2313at1.bootloader.low_fuses=0x64
attiny2313at1.bootloader.high_fuses=0x9F
attiny2313at1.bootloader.extended_fuses=0xFF
attiny2313at1.bootloader.path=empty
attiny2313at1.bootloader.file=empty2313at1.hex
attiny2313at1.build.mcu=attiny2313
attiny2313at1.build.f_cpu=1000000L
attiny2313at1.build.core=tiny
then it fails to compile with:
In file included from TinyServoExample.ino:39:0:
~/sketchbook/libraries/TinyServo/TinyServo.h:26:6: error: #error TinyServo does not support this CPU clock speed
#error TinyServo does not support this CPU clock speed
^
TinyServoExample.ino: In function ‘void loop()’:
TinyServoExample.ino:97:23: error: ‘SERVOMAX’ was not declared in this scope
Thanks for trying it out. I'm afraid that the library does not support 1MHz. If I ever get around to updating the library to include a 'detach' function, I will see about supporting 1MHz clock speeds as well.
In the meantime, you should be able to tweak it to work at 1MHz though. In the ATtinyX313 section of setupServos() in the .cpp, change the Timer1 prescaler from 64 to 8 by removing the CS10 bit:
I was under the false assumption that in order to run a tiny2313@8MHz I needed an external crystal, which isn't the case, so I can run the code fine @8MHz
Thanks !
Very helpfull and instrumental in completing my little project
This worked first time try on a ATTiny85 @ 8MHz. I could not get a stable servo signal @16MHz
As for 16Mhz problems, I can only guess that perhaps the "Burn Bootloader" process didn't work to set the fuses.
I double checked again today and setting the fuses (burning bootloader) for 16MHz seems working fine.
I tested this using the blink sketch to check if at both 8MHz and 16MHz it still blinks at a one second rate.
I use exactly the same core and boards.txt files that you described above. I have your library running at 8MHz now and cannot afford to change the core timer, as that is in use for the "manchester" coding datatransmission protocol. This is why I am so keen on getting it to 16Mhz. Better servo resolution with less jitter.
I know that blink is using the core timer, so maybe the timer 1 that I have to use at 16MHz is not properly configured. Did you test 16MHz with both timers?
Below is the code that I use for testing (I also tested your example) and both work fine on 8MHz but on 16MHz the servo moves to maximum end-point and starts humming. I wish I had a scope to see what pulse comes out.
/*
Servo connected to Pin 1 and Potmeter to Pin A3
ATtiny25/45/85
+-\/-+
RESET 1| |8 VCC
3/A3 2| |7 2/A1
4/A2 3| |6 1
GND 4| |5 0
+----+
*/
int analog1 = A3; //Analog Input
#include <TinyServo.h>
const byte SERVOS = 1; // how many servos do you have? up to 5 on ATTiny85 and 8 on ATtiny84/2313
const byte servoPin[SERVOS] = {1}; // what pins are your servos on?
// you have the option to give your servos nice names. 0 refers to the first servo pin above, 1 to the second, etc
#define SERVO1 0
void setup(){
pinMode(analog1,INPUT);
setupServos();
}
void loop(){
int an = analogRead(analog1);
an = map(an, 0, 1023, 0 , 180 );
moveServo(SERVO1, an);
delay(20); // with or without this delay the result was the same
}