|
| 1 | +/* Encoder Library - TwoKnobs Example |
| 2 | + * http://www.pjrc.com/teensy/td_libs_Encoder.html |
| 3 | + * |
| 4 | + * This example code is in the public domain. |
| 5 | + */ |
| 6 | +// Adafruit BNO055 code added by Russ76 |
| 7 | +// Red to 3.3V, Black GRND, Yellow SCL 19, Blue SDA 18 |
| 8 | +/* |
| 9 | + * rosserial PubSub Example |
| 10 | + * Prints "hello world!" and toggles led |
| 11 | + */ |
| 12 | + |
| 13 | +#include <ros.h> |
| 14 | +#include "ros/time.h" |
| 15 | +//#include <std_msgs/Int32.h> |
| 16 | +#include <diffbot_msgs/Encoders.h> |
| 17 | +#include <std_msgs/Empty.h> |
| 18 | +#include <Wire.h> |
| 19 | +#include <Adafruit_Sensor.h> |
| 20 | +#include <Adafruit_BNO055.h> |
| 21 | +#include <utility/imumaths.h> |
| 22 | +#include "sensor_msgs/Imu.h" |
| 23 | +#include <Encoder.h> |
| 24 | + |
| 25 | +// Encoder setup |
| 26 | +// Change these pin numbers to the pins connected to your encoder. |
| 27 | +// Best Performance: both pins have interrupt capability |
| 28 | +// Good Performance: only the first pin has interrupt capability |
| 29 | +// Low Performance: neither pin has interrupt capability |
| 30 | +Encoder encoderLeft(5, 6); // Default pins 5, 6 |
| 31 | +Encoder encoderRight(7, 8); // Default pins 7, 8 |
| 32 | +// avoid using pins with LEDs attached |
| 33 | +char imu_link[] = "imu"; |
| 34 | + |
| 35 | +ros::NodeHandle nh; |
| 36 | + |
| 37 | +// Check I2C device address and correct line below (by default address is 0x29 or 0x28) |
| 38 | +// id, address |
| 39 | +Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28); |
| 40 | +sensor_msgs::Imu Imu_msg; |
| 41 | +ros::Publisher imu_pub("imu/data_raw", &Imu_msg); |
| 42 | + |
| 43 | +// ROS Subscriber setup to reset both encoders to zero |
| 44 | +void resetCallback( const std_msgs::Empty& reset) |
| 45 | +{ |
| 46 | + //digitalWrite(13, HIGH-digitalRead(13)); // blink the led |
| 47 | + // reset both back to zero. |
| 48 | + encoderLeft.write(0); |
| 49 | + encoderRight.write(0); |
| 50 | + nh.loginfo("Reset both wheel encoders to zero"); |
| 51 | +} |
| 52 | + |
| 53 | +ros::Subscriber<std_msgs::Empty> sub_reset("reset", resetCallback); |
| 54 | + |
| 55 | +// ROS Publisher setup to publish left and right encoder ticks |
| 56 | +// This uses the custom encoder ticks message that defines an array of two integers |
| 57 | +diffbot_msgs::Encoders encoder_ticks; |
| 58 | +ros::Publisher pub_encoders("encoder_ticks", &encoder_ticks); |
| 59 | + |
| 60 | +void setup() |
| 61 | +{ |
| 62 | + nh.initNode(); |
| 63 | + nh.advertise(pub_encoders); |
| 64 | + nh.subscribe(sub_reset); |
| 65 | + nh.advertise(imu_pub); |
| 66 | + while (!nh.connected()) |
| 67 | + { |
| 68 | + nh.spinOnce(); |
| 69 | + } |
| 70 | + nh.loginfo("Initialize DiffBot Wheel Encoders"); |
| 71 | + std_msgs::Empty reset; |
| 72 | + resetCallback(reset); |
| 73 | + delay(1); |
| 74 | + |
| 75 | + /* Initialise the sensor */ |
| 76 | + if (!bno.begin()) |
| 77 | + { |
| 78 | + /* There was a problem detecting the BNO055 ... check your connections */ |
| 79 | + Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!"); |
| 80 | + while (1); |
| 81 | + } |
| 82 | + |
| 83 | + delay(100); |
| 84 | + bno.setExtCrystalUse(true); |
| 85 | +} |
| 86 | + |
| 87 | +long positionLeft = -999; |
| 88 | +long positionRight = -999; |
| 89 | + |
| 90 | +void loop() { |
| 91 | + long newLeft, newRight; |
| 92 | + newLeft = encoderLeft.read(); |
| 93 | + newRight = encoderRight.read(); |
| 94 | + |
| 95 | + encoder_ticks.ticks[0] = newLeft; |
| 96 | + encoder_ticks.ticks[1] = newRight; |
| 97 | + pub_encoders.publish(&encoder_ticks); |
| 98 | + nh.spinOnce(); |
| 99 | + |
| 100 | + |
| 101 | + imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER); |
| 102 | + imu::Vector<3> gyro = bno.getVector(Adafruit_BNO055::VECTOR_GYROSCOPE); |
| 103 | + imu::Quaternion quat = bno.getQuat(); |
| 104 | + |
| 105 | + //nh.loginfo("In main loop now."); |
| 106 | + |
| 107 | + // http://docs.ros.org/kinetic/api/sensor_msgs/html/msg/Imu.html |
| 108 | + sensor_msgs::Imu imu_msg; |
| 109 | + imu_msg.header.frame_id = imu_link; |
| 110 | + imu_msg.header.stamp = nh.now(); |
| 111 | + imu_msg.orientation.x = quat.w(); |
| 112 | + imu_msg.orientation.y = quat.x(); |
| 113 | + imu_msg.orientation.z = quat.y(); |
| 114 | + imu_msg.orientation.w = quat.z(); |
| 115 | + imu_msg.linear_acceleration.x = (euler.x()); |
| 116 | + imu_msg.linear_acceleration.y = (euler.y()); |
| 117 | + imu_msg.linear_acceleration.z = (euler.z()); |
| 118 | + imu_msg.angular_velocity.x = (gyro.x()); |
| 119 | + imu_msg.angular_velocity.y = (gyro.y()); |
| 120 | + imu_msg.angular_velocity.z = (gyro.z()); |
| 121 | + // https://github.com/Russ76/ros_mpu6050_node-1/blob/master/src/mpu6050_node.cpp |
| 122 | + imu_pub.publish(&imu_msg); |
| 123 | + |
| 124 | + |
| 125 | + // Use at least a delay of 3 ms on the work pc and 5 ms on the Raspberry Pi |
| 126 | + // Too low delay causes errors in rosserial similar to the following: |
| 127 | + // [INFO]: wrong checksum for topic id and msg |
| 128 | + // [INFO]: Wrong checksum for msg length, length 4, dropping message. |
| 129 | + // [ERROR]: Mismatched protocol version in packet (b'\x00'): lost sync or rosserial_python is from different ros release than the rosserial client |
| 130 | + // [INFO]: Protocol version of client is unrecognized, expected Rev 1 (rosserial 0.5+) |
| 131 | + // [INFO]: wrong checksum for topic id and msg |
| 132 | + // [WARN]: Last read step: message length |
| 133 | + // [WARN]: Run loop error: Serial Port read failure: Returned short (expected 3 bytes, received 2 instead). |
| 134 | + // [INFO]: Requesting topics... |
| 135 | + // [ERROR]: Lost sync with device, restarting... |
| 136 | + // [INFO]: Requesting topics... |
| 137 | + delay(10); |
| 138 | + // Note that https://www.arduino.cc/reference/en/language/functions/time/delay/: |
| 139 | + // Certain things do go on while the delay() function is controlling the Atmega chip, |
| 140 | + // however, because the delay function does not disable interrupts. |
| 141 | + // Serial communication that appears at the RX pin is recorded, PWM (analogWrite) values and pin states are maintained, |
| 142 | + // and interrupts will work as they should. |
| 143 | + |
| 144 | + if (newLeft != positionLeft || newRight != positionRight) { |
| 145 | + //String str = "Left = " + String(newLeft) + ", Right = " + String(newRight); |
| 146 | + //nh.loginfo(str); |
| 147 | + positionLeft = newLeft; |
| 148 | + positionRight = newRight; |
| 149 | + } |
| 150 | +} |
0 commit comments