View Full Version : ROS SetupDigitalOut LED on PIN6 not shining bright

07-21-2014, 12:51 PM
Hi all,

I want to use an LED on PIN6 or any other of the digital pins on my Arbotix2. My problem is, that the LED is very much dimmed in ROS when using rosservice call SetupDigitalOut/In when switching ON with arg-value > 0. I have tried the arduino-Blink-demo sketch and it works bright. I think it's just a matter of switching the pin as OUTPUT but I don't know how. (Ubuntu 12.04, ROS Hydro, Arbotix-latest-devel, several different LEDs).


07-23-2014, 04:39 AM
no ideas?


07-23-2014, 03:39 PM
What sketch are you using (preferably a link, copy-paste using code tags, or zip/tar file), and how frequently do the ros nodes make the service calls to change the LED state?

07-23-2014, 06:21 PM
I use ros.ino from version 0.9.2 https://github.com/vanadiumlabs/arbotix_ros-release. There are no nodes switching the LED. I was just testing with the following command:

rosservice call /arbotix/SetupDigitalOut "topic_name: 'arbotix/led_1'
value:0 or 1

The command is working, but the LED is dimmed when ON and off when OFF. I've checked resistors, wires and led. I've uploaded a simple blink-demo from:
and with that demo (without changing anything on my arbotix) the led is on(brightness) when ON and off when OFF.

if you change "OUTPUT" to "INPUT" in the following lines of the BlinkWithoutDelay demo you'd see what I mean.

// constants won't change. Used here to
// set pin numbers:
const int ledPin = 2; // the number of the LED pin

void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);

There is an option "direction" in the py-sources or somewhere else but it's not accessible from outside. If I use it, it complains about "unknown arg".

07-23-2014, 09:59 PM
There are two components to the byte actually passed to the arbotix, Direction (OUTPUT/INPUT) and State (HIGH/LOW, pull-up ENABLED/DISABLED). According to the ros.ino sketch and arbotix.py -> SetDigital(), Bit-0 of the sent byte is the direction (1 for OUTPUT, 0 for INPUT) and Bit-1 is the state (1 for HIGH, 0 for LOW). If it is Bit-0 ('direction') that is not being set correctly to 1, then the pin is almost certainly defaulting to an INPUT and then Bit-1 ('value') is either enabling or disabling the ~10kOhm pull-up resistor (which explains the very low intensity).

io.py -> DigitalServo -> __init__() sets 'self.direction' to a default of 0 to make it an INPUT by default, instead of setting it to >0 to make it an output. It appears this was the result of a partial attempt to use DigitalServo as the single class (and its 'stateCb()' callback function) for all digital pin operations, where defaulting to an INPUT is always safer than defaulting to an OUTPUT. The problem is that the services in arbotix_driver only ever call the __init__() functions of the io.py classes, so the pin always stays an INPUT (even though the name of the class explicitly requires an output pin) when not handling Digital.msg messages that might actually change the direction and state variables to their proper values.

07-24-2014, 04:42 AM
tician, thanks for the explanation. For my understanding can we brake down the options to either:
1. Hardcode the OUTPUT-direction in the .py sources
2. Leave it dimmed and go home.

I don't really want to mess Fergs sources with hardcoded stuff as I'm updating regularly. So the only option I have is 2., is it true?

The really strange thing to me is the difference of "SetupDigitalOut" and "SetupDigitalIn". I tried both and they behave identical.
My expectation was, if I use "SetupDigitalOut" it automatically sets the direction to OUTPUT.

07-24-2014, 10:31 AM
If you make the service call as usual, DigitalServo will erroneously setup the pin as an input and start a new subscriber to the ~'pin_name' topic for a Digital.msg and use the stateCb() function to change the pin state and direction accordingly. This is where I think there was a bit of code multitasking/reuse because under most circumstances an output would not need to be able to change itself to an input (you might need to be able to switch to a high-Z state in bit-bang comms, but not very common in servos), and there would be no publisher started to let you actually read the state of the pin after changing it to an input through the DigitalServo callback. The service call to DigitalSensor correctly sets the pin to an input and starts a publisher to the ~'pin_name' topic for a Digital.msg and has no callback function to handle external nodes trying to control the pin by publishing Digital.msg to the pin topic.

If you publish a Digital.msg for the pin you want after you've made the service call, you should be able to turn the pin into an OUTPUT without messing with any of fergs' code. However, any time you make a subsequent service call it will reset the pin to an input and restart the subscription to the pin topic.

Otherwise, the change to fix it should consist of a single character in io.py -> DigitalServo -> __init__():

self.direction = 0


self.direction = 1

07-24-2014, 02:19 PM
Ok, publishing a Digital.msg for the pin "after" the service call I never tried. I'll try it.

This is the command I used in the beginning of my tests with various options like -r 10:

rostopic pub /arbotix/led_1 --once arbotix_msgs/Digital "value: 255"
rostopic pub /arbotix/led_1 --once arbotix_msgs/Digital "direction: 255"

The second command causes warnings of unknown arg.

Thank you for clarification, tician. With your help I could go deeper into Fergs code and mess with it :wink:.

07-30-2014, 09:23 AM
After banging around a bit I found a solution, thanks tician.

1. Call service SetupChannel-type
2. Publish Digital.msg-type

It doesn't matter if the Digital.msg publisher already publishes to the led_1-topic, so the order is not important.
Putting the service call in main didn't work for me, maybe had to wait for the arbotix-service to come up, so I put it into callback (not the best solution).

#include <ros/ros.h>
#include <sensor_msgs/RegionOfInterest.h>
#include <arbotix_msgs/Digital.h>
#include <arbotix_msgs/SetupChannel.h>

ros::Subscriber ROIs;
ros::Publisher LEDp;

arbotix_msgs::Digital dmsg;

ros::ServiceClient client;

unsigned int sq = 0;

void roi_cb(const sensor_msgs::RegionOfInterest msg)

arbotix_msgs::SetupChannel srv;
srv.request.pin = 6;
srv.request.rate = 10;
srv.request.topic_name = "led_1";
srv.request.value = 255;

if (client.call(srv))




dmsg.header.seq = sq;
dmsg.header.frame_id = "led_1_pin6";
dmsg.header.stamp = ros::Time::now();
dmsg.value = 255;
dmsg.direction = 255;



int main(int argc, char** argv)
ros::init(argc, argv, "pan_tilt");
ros::NodeHandle nh;

ROIs = nh.subscribe("roi", 100, &roi_cb);

LEDp = nh.advertise<arbotix_msgs::Digital>("/arbotix/led_1", 1000);

client = nh.serviceClient<arbotix_msgs::SetupChannel>("/arbotix/SetupDigitalOut");

return (0);