Monday, May 23, 2022

Serial problems

 So last time I left the robot, I was able to control it with a keyboard, but it had issues stopping.


Today I revisited the issue. 

I started by Tuning the PID controller on the Arduino, that proved really unproductive, so I started wondering if this is a "garbage in=garbage out" problem. The lowpass filter I got from Curiores (https://gist.github.com/curiores), wasnt performing the way I wanted, do I found another signal filtering library by Martin Bloedorn (https://github.com/MartinBloedorn/libFilter) which seemed to work a lot better. Probably because its a higher order filter.

I also noticed that my the battery voltage dropped quickly and determined how well the PID worked. So I might need a more reliable battery source than just 12 NiMH batteries. 

I also bought a kinect recently for 20$ in hopes of putting it on the robot to do fancy visualizations. It will also require 12 volts, so I'll need to share the power between the motors and the kinect.

Note to self: to start the kinematics node do

rosrun Kinematics kinematics.py

its a capital K

So after I filtered the signal and started all the nodes on the pi, I was able to drive it with the keyboard and have it stop, however there is still some funky business going on.

  • The robot really likes to turn. In fact it likes it so much that it doesn't stop turning.
  • Sometimes it won't obey the commands, as if it read commands from somewhere else. 
  • The wheels behave independently of each other.

The serial node only works at 57600Hz, even though the arduino is supposed to be running at 230400Hz. When I was testing on the Arduino alone none of this seemed to be happening, so I think the issue lies in the serial interface, so the next step is to configure some logging. Or I could just wing it and try to get the robot to follow a path. Or just give up on the velocity aspect and only tune for position.



Wednesday, May 11, 2022

ROS Problems

 

When integrating a bunch of different components there are certainly some expected difficulties. The way that ROS nodes work is by sending each other messages that are published to certain topics.

A single node can have multiple subscribers and publishers in it that can send and receive messages.

Each message has a certain type and a definition file that controls what is sent in the message.

I ran into a problem when trying to send over a list of 4 integers that would represent velocities on the 4 motors.

ROS has a message type for a multi-dimensional array, but not a single array. To send a multiple dimension array message, you need to specify a bunch of parameters such as dimensions which I didn’t want to bother with.

So, I set out to create my own custom message type. To do so I first needed to create a package, then create a message file on my raspberry pi. This was relatively easy, however I quickly realized that I also needed to generate a header file for the Arduino to understand the message. This is where the trouble began.

I followed the tutorial for header file generation, but it didn’t work!

What I was missing is that instead of rosclient I should have used rosArduino in the command. And the destination needs to be empty of ros lib. After fixing a couple of other issues I was finally able to generate the h file.

Then I learned how to use scp to copy the file from the raspberry pi onto windows, so I could put it into the Arduino library.

After doing all that I was ready to test.

To my great disappointment, the raspberry pi couldn’t sync to the Arduino. Something about my custom message was messing it up, and I just kept the same error over and over again.

Finally, I gave up and decided to use the overkill MultiArrayFloat32 message. Float64 is not accepted by the Arduino!

When I tested before I just used the rospub command and published an empty message or a couple of integers, but MultiArray was a whole other beast.

I couldn’t figure out the format for the life of me. BUT. If you push tab it autocompletes it for you!

After I learned that I was able to publish a list of integers to the robot and it turned on the motors!

Huge success!

Next, I included a publisher node into my kinematics node, which published a Multi array message. Publishing messages that way was a lot easier as I was able to use the attributes of the message object.

PID tuning

One thing that is really important in robotics is PID. Which stand for proportional, integral, differential methods of control.

Essentially it is a method for controlling the system based on the error.  For me this was essential, because my motors spin even after you cut off the power. I started with making a PID controller to control position.

I created a controller function and started graphing the target position as well as the actual.

I frequently ran into the problem where the wheel would oscillate around zero, never fully stopping.

This was super annoying and disheartening because I wanted my robot to be really precise. Eventually I ended up putting in a tolerance of 5% and telling the robot to shut off the motors if it got within that margin. This improved the issue drastically.

However, the wheels performed differently. At this point I was considering making a controller for each individual wheel and creating their own constants, but that seemed too time consuming.

The good news was that on the ground the robot wheels didn’t oscillate, because of the friction. Although the robot didn’t really drive straight.

I got a 3d printer

 

Some big updates to the robot!

I have finally bought a 3d printer and have been busy making parts. I designed columns to support a second deck and secured them to the chassis with m3 bolts and nuts. I used a clever technique where the nut sits inside a recessed space and are held in place by the material, this way it acts as a threaded insert and doesn’t require a wrench. Then I printed a 2-part deck for the robot, my printer wasn’t big enough to do the whole thing in one go.

So now I can finally mount the raspberry pi and its battery securely. The battery sits inside a pocket and the raspberry pi sits on top of that. I don’t have standoffs, so I decided to just screw it on and use nuts for spacers. Might need to add head sinks to the pi too, hopefully it won’t melt the plastic or anything.

So now that everything is secured, I can test the driving capability without worrying about everything falling off. Woohoo!

On the electronics side, I figured out how to get a reliable reading from all 4 encoder, so now I have a position count.

I have also made a PID controller, to control the motor. Otherwise, its impossible to get them to stop when you want. It seems that they keep spinning past the cutoff time.

The key insight is that you can make a  template in C, that can be applied to the same function with different parameters. This allowed me to clean up the code significantly.

So, after I figured all of that out, I managed to set a position target for each wheel. The PID performance was still a bit inconsistent, but it kind of worked. The problem is that I don’t want the robot to move at maximum speed towards each target and I’m not sure how to use the kinematic equations with a position target. Plus with speed I could use the teleop_twist_keyboard node, which would let me set a speed with a keyboard and pass the twist message to my kinematics equations which could then pass a motor velocity to the Arduino.

So now I am trying to get a reading for speed. And oh boy that is a can of worms and a half. Basically the most reliable method is to count the number of pulses from the encoder within a specified time interval

d/delta(t)

The problem is that my encoders are incremental. Which means that they go up in discrete steps. Think of it as walking up a staircase instead of a hill.

And that creates a TON of noise, when you try to calculate velocity. The typical solution to this problem is to implement a low pass filter that will filter out the high frequencies and keep the low ones. I tried an update equation from a low pass filter of 25Hz, and that made the signal a lot better. But I have this problem where my filtered velocity doesn’t reach the target, and the unfiltered velocity peaks at the target.

I have no idea why this is happening. Maybe I’m setting a target too high? I can experiment with slower velocities? Creating a low pass filter on the Arduino feels like trying to paint the Mona Lisa with blood spurting out of your cut off finger. Very painful and ugly.

So I’m considering just passing the encoder readings to the pi and letting it do the complicated signal processing and maybe even the control. I’m just worried it won’t be fast enough. The whole point of the Arduino was to have fast low level control, which it seems I can’t do without a better filter! AAAAA!

It sounds like I have to get back to the complicated math of my 4th year control systems course, and get into stuff like Discrete Fourier Transform and Bode diagrams.

Hopefully, I don’t need to get to much into the weeds, I just want the speed control to work.

I am also experimenting with a higher baud rate, might be faster.

In more happy news though, I got the teleop twist to work! I figured out how to use a MultiArray message to communicate to the Arduino and now I can drive the robot with my keyboard on my laptop!

It has an issue with stopping for some reason. It doesn’t like to come to a complete stop. And there seems to be a delay between the keyboard input and the wheels.

Thursday, January 20, 2022

 Soo, I'm having some electrical problems and I can't figure out why.

I can get 3 wheels to turn but the front right won't move. 

I might have burned out the L298N motor controller. So I'm gonna have to start over with the wiring setup. 

Currently I have a huge mess of wires that's hidden under a plastic box from a yogurt container. Its time to get into that mess and figure out where the problem is.

Luckily I have a volt meter and a small oscilloscope!

I have also discovered that the encoder library which I want to use requires that you connect the encoders to pins with interrupt capability. The uno has only 2 pins like that and I need 8, since I have 4 motors with A and B signals. So I have decided to switch to an arduino mega. It has way more pins so maybe I can also get rid of the shift register.

So the plan is to trouble shoot the electrical stuff, switch to a mega, and setup up the encoders.

 

Currently I was not able to establish how many ticks the encoders provided per rotation, the results were just too inaccurate.

I have also switched to a raspberry pi 4 because as it turns out the 3 A model didn't have enough ram.

 

Tuesday, November 23, 2021

Blink

Okay so today I added that line to bashrc

and I managed to turn on the wheels by using the raspberry pi!

Basically I modified the blink script that test serial communication. In this script the Arduino acts as a subscriber node and uses a call back function. When it receives a message it calls that function and turns on an LED.

 I was able to modify it to run the motors instead.

 

One wheel isn't turning properly so I'm gonna charge the batteries and see what happens.

Problems:

The ssh terminal is slow to respond

The sending speed of the message is very slow

wheels are inconsistent

Good things:

I figured out that I can just make teleop twist work for me

With this node I can send a vector for the robot to follow using the keyboard

I just need a node in between the arduino and the teleop to translate the vector into stuff that the arduino undestands.

Saturday, October 30, 2021

Hello world!

 Ok so I finally got Arduino to day hello world to the raspberry pi 

some things to not

the port name is ttyACM0

The default baud rate on the pi is high 57600

I need to add this line to the bash_rc file, so that I don't need to run it in every terminal

 source catkin_ws/devel/setup.bash
 

 The  arduino dev environemnt is still not ideal, i don't know why. I think it gets angry if you don't have each script in its own folder.

 

This tiny bit of work took me like 2 and a half hours because I had to do so much setup. 

But its progress!!

 

Sunday, October 17, 2021

Restarting

 Hey, I'm finally getting back into this project. I haven't really been working on it since my job keeps me busy. Anyways.


I've had to do a whole bunch of resetup stuff to be able to work on this again. Since my last update I have moved, started a new job and destroyed my computer. Also my cat chewed through the power cable of the robot.

First I had to solder the connections on the robot back together. 

Then I had to reinstall a whole bunch of stuff on my computer since I formatted my hard drive.

This included the Arduino IDE, putty, an ip scanner I use to find the pi etc.

I also got tired of the Arduino IDE since its barely usable when compared to Visual Studio Code that I use for work.

So I installed Visual Studio and managed to find a good Arduino extension.

Its called Visual Micro

https://www.visualmicro.com/

I was finally able to clone my repo again and start working on the project.

Right now im just working on getting hello world through the serial connection between my Arduino and my Raspberry pi. 

I'm having trouble getting the ros serial noetic package on the pi.

And I still have no idea how to deal with the encoder, in any case I've now made my code on github public :)

https://github.com/bus0v/robot

NEW Project Autonomous underwater vehicle!

  I have been more and more interested in Autonomous Underwater Vehicles and ocean exploration. I live on the coast with direct access to th...