Giter Club home page Giter Club logo

servoinput's Introduction

Servo Input Library

arduino-library-badge Build Status

This is an Arduino library that allows you to read the position of servo motors via their signal wire without delay. You can use this library to read RC receiver channels, find the motor positions of robotics, or debug other servo motor projects.

For more information, see the article and tutorial on PartsNotIncluded.com.

Getting Started

#include <ServoInput.h>

ServoInputPin<2> servo;

void setup() {
	servo.attach();
}

void loop() {
	float angle = servo.getAngle();  // get angle of servo (0 - 180)
}

Connecting Servos

Servo motors are driven by three pins: signal, power, and ground. To use this library, each 'signal' pin needs to be connected to an interrupt-capable I/O pin and the servo's ground wire must be tied to the Arduino's GND pin.

Signals and Interrupts

The Servo Input library uses external interrupts to keep track of servo positions without delaying the rest of your sketch. In order for the library to work, you must connect the servo signal wires to interrupt-capable pins.

BOARD DIGITAL PINS USABLE FOR INTERRUPTS
Uno, Nano, Mini, other 328-based 2, 3
Uno WiFi Rev.2 all digital pins
Mega, Mega2560, MegaADK 2, 3, 18, 19, 20, 21
Micro, Leonardo, other 32u4-based 0, 1, 2, 3, 7
Zero all digital pins, except 4
MKR Family boards 0, 1, 4, 5, 6, 7, 8, 9, A1, A2
Nano 33 IoT 2, 3, 9, 10, 11, 13, A1, A5, A7
Nano 33 BLE, Nano 33 BLE Sense all pins
Due all digital pins
101 2, 5, 7, 8, 10, 11, 12, 13

Original table from arduino.cc/reference, modified to show only CHANGE interrupts

Some third party boards such as the Teensy 3.2 and the ESP8266 support external interrupts on all pins. Be sure to check the documentation for your board before connecting your servos.

Each servo's signal wire needs to be connected to a separate pin. If you do not have enough interrupt-capable pins on your board, you can also use pin change interrupts. ServoInput integrates with NicoHood's PinChangeInterrupt library for AVRs - just import Nico's library before ServoInput and any necessary pin change interrupts will be added automatically. Be aware that due to the extra overhead pin change interrupts are not as accurate or reliable as external interrupts. Keep that in mind when choosing which pins to connect to which servo.

Power Levels

Often servo motors are driven at higher voltages than your Arduino can handle. In this case, you will need either a level shifter or a voltage divider for the signal wire. Use a multimeter to check the servo's voltage level before making your connections.

Warning: if the servo's voltage is above the acceptable voltage for the Arduino, connecting the signal wire directly risks permanently damaging the board. Be smart and check before you connect anything.

Common Ground

If your servo is not powered by the Arduino running ServoInput, you must connect the ground wire from the servo's power supply to the ground pin of the Arduino so that they share a common reference.

If you are measuring multiple servos that use the same power supply, you do not need to connect the ground wire for each servo. Just the one is fine.

License

This library is licensed under the terms of the GNU Lesser General Public License (LGPL), either version 3 of the License, or (at your option) any later version.

servoinput's People

Contributors

dmadison avatar seantfish avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

servoinput's Issues

Library does not compile on Arduino Nano 33 BLE

Hi David, the library works great on Uno & Mega, however, it does not compile on Arduino Nano 33 BLE.

I saw there are a few other folks that left comments on forums about this issue, so I guess more people could find this useful.

Hope you have some time to address it.

Add support STM32F401

The library is very good. Thank you. Can you add support for STM32F103, STM32F401?

Couple of Comments not issues

First thanks for making this. It looks really clean.

  1. Works with ATTiny1626 and the megaTinyCore core for the newer ATTiny CPU chips (which are really superior to the ancient ATMega168/328 chips)

  2. In your examples you assume the signal range is symmetrical around the average of the max and min values. This is not always true especially for pistol style RC car radios. I always store the center point along with the max and min for this situation.

  3. When converting from pulse time to output value I always have a deadband around zero so the output isn't' jittering slightly above and below zero constantly. Then ramp linearly or exponentially to the max/min from the edge of the deadband. I realize this is extra code but you have most of it already done with the map function.

Again thanks for putting this together. Much appreciated.

Chris

Will this work with current ESP32?

I'm wondering if this library is also applicable for esp32? because i broke my nano and i only have esp32 as a spare for a rc car project thanks

Support for Due

Hello David,

This project is exactly what I am looking for, but I am developing with a Due. Would it be possible to add support for this platform?

Thanks,

Eric

Needs lost signal timeout function

Additional function request:

For reliability in real applications it is important to know if the input signal has been lost due to a broken wire or interference or whatever. Basically a timeout function from the last valid pulse reception on each channel.

Currently the user must keep track of the time since the last pulse reception for each channel since getPulse() keeps returning the last valid value. Since the library is already interfacing with the microsecond timer it would seem easy to add a timestamp on reception of a valid pulse for each input. Then something analogous to available() could be used to check if the pulses are still coming in OK. Perhaps a status() or timeout() or something like that method could be added to allow the user a quick way to make sure all is OK and take safety action if not.

Thanks,
Chris

wrong angle values

Hi
Using ServoInput in combination with other functions, from time to time the function "servo1.getAngle()" delivers wrong values in a row: 0's or 180's. One possible reason could be, that the extreme values come due to other interrupt routines, that interferes with ServoInput. I bypassed this problem by simply not using the values 0 or 180. These extreme values are not relevant for my application.

Here is my simple code example:

#include <ServoInput.h>
#include <Servo.h>

ServoInputPin<0> servo1;
ServoInputPin<1> servo2;

Servo myservo1; // create servo object to control a servo
Servo myservo2; // create servo object to control a servo

void setup() {
Serial.begin(115200);
myservo1.attach(4); // attaches the servo on pin 9 to the servo object
myservo2.attach(5); // attaches the servo on pin 10 to the servo object
}

void loop() {
int angle1 = servo1.getAngle(); // get angle of servo (0 - 180)
int angle2 = servo2.getAngle(); // get angle of servo (0 - 180)
if (!((angle1==180)or(angle1==0))){myservo1.write(angle1);} else {Serial.println(angle1);} // sets the servo position according to the scaled value
if (!((angle2==180)or(angle2==0))){myservo2.write(angle2);} else {Serial.println(angle2);} // sets the servo position according to the scaled value
}

board MKR WiFi 1010 not supported

Hi
Thank you very much for your effort to develop this library!
It seems, that MKR boards are not supported. As mentioned in the error message, I ask you to add this board (or all MKR boards).
Thank you very much! Adrian

Error message from arduino compiler:

"In file included from C:\Users\adria\OneDrive\Dokumente\Arduino\libraries\ServoInput-1.0.0\src/ServoInput.h:27:0,

             from C:\Users\adria\OneDrive\Dokumente\Arduino\libraries\ServoInput-1.0.0\examples\BasicAngle\BasicAngle.ino:29:

C:\Users\adria\OneDrive\Dokumente\Arduino\libraries\ServoInput-1.0.0\src/ServoInput_Platforms.h:44:2: error: #error "The ServoInput library does not support this board (platform). Please create a feature request here: https://github.com/dmadison/ServoInput/"

#error "The ServoInput library does not support this board (platform). Please create a feature request here: https://github.com/dmadison/ServoInput/"

^~~~~

Multiple libraries were found for "ServoInput.h"
Used: C:\Users\adria\OneDrive\Dokumente\Arduino\libraries\ServoInput-1.0.0
exit status 1
Error compiling for board Arduino MKR WiFi 1010."

Table is incomplete

Hello, looks like a great library

just wanted to let you know that on the arduino website the column with "Uno WiFi Rev.2" now also includes the "Nano Every" which I assume this library should also work for

Interrupt related compilation issue with UNO R4 Minima

When trying to compile code that uses ServoInput library - one of the examples for instance - the compilation fails with multiple error reports related to a missing interrupt capability. This happens even though the HW has interrupt capable pins D2 and D3 just like the earlier UNO versions.

The issue is easily reproduced by just selecting a code example accompanied with this library and compiling first with Arduino UNO selected. the switch to Arduino UNO R4 to see compilation fail.

This may be related to a similar issue found with ESP32. It could also have something to to with the interrupt handling of Renesas RA4 MCU.

Compilation Issue on Arduino Nano ESP32

Hello,

I'm having a strange issue while compiling this library for a Nano ESP32. It looks like the arguments for attachInterrupt were changed for this board. Is there a possible workaround for this?

Console output:

Arduino\libraries\ServoInput\src/ServoInput.h:99:19: error: macro "attachInterrupt" requires 3 arguments, but only 1 given
attachInterrupt();
^
Arduino\libraries\ServoInput\src/ServoInput.h:106:23: error: macro "attachInterrupt" requires 3 arguments, but only 1 given
void attachInterrupt() {
^
Exit status 1

Thank you,
Matthew

Trouble with more than two servo inputs

I have three servo inputs connected. Each one works individually. However, when all three are connected one of them always fails to work properly. I have three switch channels connected from channels 4, 5 & 6. Chanel six is a momentary switch, channel 5 is three position and channel four is a two position. Channels 4 and 6 work flawlessly. If I plug in channel 5 then it only reads position 2 & 3. Also, when channel 5 is plugged in channel 6 works intermittently.

I'm using an Arduino Nano Every with Ch 6 on pin 12, Ch 5 on pin 8 and Ch 4 on pin 10. The ground is connected to pin 29.
Code:

#include <SoftwareSerial.h>
#include <ServoInput.h>
//Setup mappings for receiver channels- each channel is mapped to a channel on the transmitter
ServoInputPin<12> ch6; //momentary switch
ServoInputPin<8> ch5;  //three position switch
ServoInputPin<10> ch4;  //two position switch
const int MT = 2;
const int Three = 3; 
int sound_clip = 1;



SoftwareSerial mySerial(2, 1); // RX, TX... Nano Every Tx=1  Rx=2

void sendCmd(int cmd, int lb, int hb, bool reply = false)
{ // standard format for module command stream
uint8_t buf[] = {0x7E, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF};
int16_t chksum = 0;
int idx = 3; // position of first command byte

buf[idx++] = (uint8_t)cmd; // inject command byte in buffer
if (reply) buf[idx++] = 0x01;
else buf[idx++] = 0x00;// set if reply is needed/wanted
if (hb >= 0) // if there is a high byte data field
buf[idx++] = (uint8_t)hb; // add it to the buffer
if (lb >= 0) // if there is a low byte data field
buf[idx++] = (uint8_t)lb; // add it to the buffer
buf[2] = idx - 1; // inject command length into buffer
buf[idx++] = 0xEF; // place end-of-command byte

mySerial.write(buf, idx); // send the command to module
// for (int i = 0; i < idx; i++) // send command as hex string to MCU
// Serial.printf("%02X ", buf[i]);
// Serial.println();                                                                                                                                                                                                                                                                                                   b
}

void setup()
{

Serial.begin(115200); //for console debugging
delay(2000); //Allow Serial to start up

Serial.println("starting ");
mySerial.begin(9600); //communicate with DF Player
delay(3000); //Allow SoftwareSerial to start up

Serial.println("Stop anything playing"); //in case anything is already playing on reset
sendCmd(0x0E, 0, 0, false);
delay(200); //give a delay for the DF Player to execute the command

//Serial.println("Now volume ");
sendCmd(6, 30, 0, false); //command code can be in decimal too.

//Serial.println("Starting Player");
//sendCmd(0x01, 0, 0, false); // Send a "next track" command that turns play mode on
delay(1000);
Serial.println("_____________________________________");

}

void loop()
{
 //Momentary Switch Channel 6 HS - Play sound
int channel6 = ch6.map(1, MT);
//Serial.println(channel6); //Debugging to read the channel

if (channel6 == 2){
  Serial.print("Sound Activated");
  delay(300);
  play_sound();
}

//Three position switch Channel 5 SE - Select up scanner sound; middle no sound; down turbo boost
int channel5 = ch5.map(1, Three);
//Serial.println(channel5); //Debugging line for channel5
 if (channel5 == 3){
  delay(500);
  Serial.println("Turbo Boost");
  sound_clip = 6;
  }

if (channel5 == 2){
  delay(500);
  Serial.println("Scanner");
  sound_clip = 4;
  }



//Two position switch Chanel 4 SF - Select Sound
int channel4 = ch4.map(1, MT);
if (channel4 == 2){
  delay(500);
  sound_clip = sound_clip + 1; //Increase the number of the selected sound file up to 16 and then reset to 1
    if (sound_clip > 16){
      sound_clip = 1;
    }
  Serial.println("Sound select change");
  Serial.print("Selected sound:");
  Serial.println(sound_clip);
  delay(300);
  }
}

void play_sound() //Subroutine to play the selected sound file
{
  Serial.println("Play sound ");
  Serial.print(sound_clip);
  sendCmd(0x0F, sound_clip, 1, false); //play selected track in folder 01
  delay(200);
  Serial.println(" ");
}

Its a great library though! Any help is appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.