ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

How to really blink an LED on an arduino through ROS

asked 2017-09-14 16:43:02 -0500

paulrusu gravatar image

I set up ROS with an arduino and successfully implemented the blink-example. However, I would like to really make it blink, e.g. to turn the LED on and off with a high frequency. Unfortunately, I have not managed to do that. The code I tried is:

#include <ros.h>
#include <std_msgs/Empty.h>

ros::NodeHandle  nh;

void messageCb( const std_msgs::Empty& toggle_msg){
digitalWrite(13, HIGH-digitalRead(13));
delay(100);
digitalWrite(13, LOW-digitalRead(13));
delay(100); // blink the led
}

 ros::Subscriber<std_msgs::Empty> sub("toggle_led", &messageCb );

void setup()
{ 
pinMode(13, OUTPUT);
nh.initNode();
nh.subscribe(sub);
}

void loop() 
{  
nh.spinOnce();
}

As can be seen, I tried to give the command to be executed in the message as if the message contains the actions to be carried out, but it did not work so I was wondering what the proper way to do sequences of action with one message would be?

Thank you.

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
1

answered 2017-09-14 19:31:17 -0500

jayess gravatar image

updated 2017-09-16 13:41:14 -0500

I believe that you got some inspiration from this tutorial: http://wiki.ros.org/rosserial_arduino...

The line

digitalWrite(13, HIGH-digitalRead(13));

will toggle the LED for you. First, it reads the pin digitalRead(13), then it writes it digitalWrite. The portion that says HIGH-digitalRead(13) does the alternating part. If digitalRead(13) is high then your LED will turn off and if it's low your LED will turn on.

  • HIGH - HIGH = LOW therefore turn off LED
  • HIGH - LOW = HIGH therefore turn on LED

The callback is the trigger for this behavior. Therefore, all you need to do to get your LED to blink at a high frequency is to publish an std_msgs/Empty message along the toggle_led topic at whatever rate you want.

Now, about the delays. You should remove them and just do it how the tutorial showed it. Callbacks should be quick so that you can react to the incoming messages. With two delays of 100ms each you won't be able to blink the LED at a high frequency.


Edit:

I'd be cautious about looping in a callback like so:

void messageCb( const std_msgs::Empty& toggle_msg){
  for (int thisInt = 1; thisInt < 2000; thisInt++) {
  digitalWrite(8, HIGH-digitalRead(8)); delay(100); 
  // blink the led
  }
}

The reason is that callbacks should be quick in order to react to incoming messages. But, here the loop is running for almost 200s! You're going to be in that function for over 3 minutes not doing anything else, ignoring all subsequent messages. Now, for this use case you're ok because it's trivial. But, for anything of consequence this is going to cause you trouble. Usually, I'd say an action is the way to go, but rosserial_arduino doesn't support that (as far as I know) so you'll either have to write another node to control the publishing of the message that controls the blinking or find another workaround.

Otherwise, your first code block looks like it works.

edit flag offensive delete link more

Comments

@paulrusu: if this solved your problem, please click the check mark to mark it as correct.

jayess gravatar image jayess  ( 2017-09-15 16:48:55 -0500 )edit

Thank you for your answer, but this was not quite what I meant. Obviously, I understand that every time one publishes a message, the LED is turned on or off. It is a switch. What I was interested in was the usage of one message to trigger a whole array of actions and not just one.

paulrusu gravatar image paulrusu  ( 2017-09-16 07:57:38 -0500 )edit
0

answered 2017-09-16 08:28:13 -0500

paulrusu gravatar image

The question really was for me to use the message to carry out more than one action. The solution that I found was to The solution I came up with for the specific problem was to take another output to act as a switch and have its value control the actions to be executed in the loop section where the actual blinking is implemented. Please see the code below:

#include <ros.h>

#include <std_msgs/Empty.h>

ros::NodeHandle  nh;

void messageCb( const std_msgs::Empty& toggle_msg){
  digitalWrite(8, HIGH-digitalRead(8));   // blink the led
}

ros::Subscriber<std_msgs::Empty> sub("toggle_led", &messageCb );

void setup()
{ 
  pinMode(8, OUTPUT);
  pinMode(13, OUTPUT);
  nh.initNode();
  nh.subscribe(sub);
}

void loop()
{  
  nh.spinOnce();
   if(digitalRead(8) >= HIGH){
    digitalWrite(13, HIGH-digitalRead(13));
    delay(100);
    digitalWrite(13, HIGH-digitalRead(13));
    delay(100);
 } // blink the led
}

What I also gathered was that you actually can put as many commands as you want into your message like so:

void messageCb( const std_msgs::Empty& toggle_msg){
  for (int thisInt = 1; thisInt < 2000; thisInt++) {
  digitalWrite(8, HIGH-digitalRead(8)); delay(100); 
// blink the led
}}

This obviously makes it blink 1000 times.

edit flag offensive delete link more

Question Tools

Stats

Asked: 2017-09-14 16:43:02 -0500

Seen: 2,196 times

Last updated: Sep 16 '17