Monday, December 26, 2011

A note about Arduino serial

When reading strings through Arduino Serial, I usually make a string variable and concatenate onto it as each Serial.read() character comes in.

Suppose Serial communication occurs one string at a time. If you collect each string with a while(Serial.available()) loop, a problem arises. The first three characters, if the string is longer than three characters, is truncated. Why?

I fixed this problem by adding a small delay (~5 ms, could be less, I did not play with it and it depends on the amount of code between the delay and character reception) after every three characters. It appears Serial communication is done in packets of three, with a small delay in between, making Serial.available() false every three characters for a brief period of time.

Updates

I have my biggest project yet coming up soon. I have not been posting about it, even though I have been working on it for several weeks, and thinking about it and planning for months. What is holding me back is that I am on break, and school is closed. I need to use my school's water-jet cutter, and I will do that ASAP when school starts and the machinery becomes available.

Simple LCD Character Display and Arduino Uno

It is easy to hook up and use a character display to an Arduino. Turns out, a specific driver that comes with LCD displays that is very common is the HD44780 driver and there is an Arduino library specifically for it: LiquidCrystal.

It is very easy to use in software and in hardware. The following picture is from the documentation for my screen that I bought on eBay (JHD-204A), showing the pin configuration and power characteristics.

The official Arduino documentation on LiquidCrystal is all you need and it can be found at: http://www.arduino.cc/en/Tutorial/LiquidCrystal. Actually no other parts than connecting wires are required. The potentiometer mentioned in the above reference is just for contrast adjustment.



I personally prefer wire wrapping to soldering when I can, mainly because I am not good at soldering and I do not like toxic fumes. Here I had to solder the header pins onto the LCD display pins, but after that wire wrapping all the way. It was fun. Wire wrapping wire and header pins are an awesome combination.

One inevitably runs into errors when installing the driver for the Arduino Uno on my Windows 7 PC. I thought it was just an error on my computer specifically but apparently it is the norm for now. The solution is found on the official Arduino website here. They acknowledge that the error occurs no matter what, "despite [Window's] best efforts".

Tuesday, December 20, 2011

Using an XBOX controller for non-XBOX things

If you cut the cord on the wired controller there are 4 wires: red and black for power, and green and white for data signals. So apparently if you simply hookup up the power and leave the data wires floating you cannot immediately utilize some of its basic parts, such as the potentiometers. Now that I think about it, I guess I should have tried to ground the signal wires to see if the pots and stuff work, instead of leaving the signal wires floating.

What I did was I found the potentiometer solder points and soldered directly to those, providing power and using the signal output. There are potentiometers on the left and right triggers, and 4 total on both joysticks. All of the potentiometers have three grouped pins in a row, and the middle is the signal. I supplied power from the Arduino to the outer pins and hooked up the middle signal to an Arduino input pin.

Supplying the main power to the controller does let the buttons work, however. These are pressure-sensitive touch pads that go low when pressure is applied, so they are pulled up. There is a space next to these pads available for a wire to be soldered. I had to scratch off the lacquer with a razor blade for the solder to stick.

The left and right "bumper" buttons are simple momentary push buttons. No confusion there, just use a DMM to find where you would want to connect.

Using the XBOX controller for its basic components is pretty straightforward, but soldering may be a little trouble because one of the potentiometer's pins are underneath the trigger assemblies.

Sunday, December 11, 2011

Omniwheel vehicle speed consistency

I am currently working on an omniwheel drive vehicle with a rather... unique control system. I am estimating it will be done by January. It involves wireless Arduino serial communication via XBEE, water-jet cut custom aluminum parts, h-bridge PWM DC motor controllers, and mutilated IKEA furniture, haha.
This post is about some speed control considerations on a vector-based control algorithm. Depending on what direction you going in, the speed will differ, because the wheel orientations change. Obviously, for a good human-operated vehicle this speed difference must not be too great. If the direction is aligned with the wheel's normal rolling direction, the speed will be at a maximum. The wheel most aligned with the direction of movement will dictate the top speed of the vehicle. All other wheels will provide moment balance and extra torque.
Below are some plots showing the normalized (meaning min is 0, max is 1) speed vs. direction, in radians. The different plots are for different numbers of motors/wheels installed on the vehicle.

As you can see, for 3 and 4 motors the speed difference is quite significant. For three motors, the lowest speed depending on the direction of vehicle movement can be about 14% lower than the normal speed (in the graphs it would be 1). Four motors fares even worse, which can be surprising at first glance. Four motors give a minimum speed around 30% lower than the normal speed.
A few interesting patterns can be seen here. The number of dips equals the number of wheels/motors if the number of wheels/motors is odd, and twice the number of wheels/motors if the number is even. Also, locally the speed difference is minimized if the number of wheels/motors is odd. 5 wheels/motors is a reasonable number that gives an acceptable speed difference, <5%. Of course, all of this can be fixed to give virtually no speed difference consistent speed in the controller's software.
This was a very interesting investigation! The code to generate the plots above was written in MATLAB and is included below (MATLAB is not free, but SCILAB is! And it is very similar! It will probably run the code with little or no modification!):

%FPS bot testing
offsetAngles = [0 0 0 0 0];%Just the difference in angle between frontmost motor and forward direction.
motorCounts = [3 4 5 6 7];
motorAngles = 2*pi./motorCounts;
for j = 1:numel(motorCounts)
mvec = zeros(motorCounts(j),2);
for k = 1:motorCounts(j)
mvec(k,:) = [cos(offsetAngles(j)+(k-1)*motorAngles(j)) -sin(offsetAngles(j)+(k-1)*motorAngles(j))];
end
resolution = 10000;
mag = zeros(resolution,1);
theta = linspace(0,2*pi,resolution)';
directionVector = zeros(resolution,2);
directionVector(:,1) = cos(theta);
directionVector(:,2) = sin(theta);
currentMag = zeros(motorCounts(j),1);
for k=1:resolution
for i=1:motorCounts(j)
currentMag(i) = abs(mvec(i,:)*directionVector(k,:)');
end
mag(k) = max(currentMag);
end
figure;
plot(theta,mag);
ylabel('Normalized speed magnitude');
xlabel('Direction (radians)');
title(['Normalized speed magnitude vs. direction, ' num2str(motorCounts(j)) ' motors']);
end

Saturday, December 3, 2011

Parallel efficiency tests

Hello, today I bring the results of some quick parallel efficiency tests. I run on each of three computers two identical cases: one using a single core and another using 4 cores. To get an efficiency factor, I divide the time it took to run the 4-core case by 4 times the time it took to run the case on a single core. In the best case the result is 1, meaning there was no waste in multiple-core communication/overhead. But... we see this is not the case:

As you can see, the results are quite bad. I am not sure what causes this inefficiency. One reason I have seen floating around the internets (both the good and bad internets) is that the primary cache (L1?) size severely limits this. I have also seen that the secondary and below cache (L2, L3) sizes are not very useful in this application at least.

Computer 1 has an i7-2600 core, Computer 2 has an i5-750, and Computer 3 has a different i5 (Q9550). The memory is more than enough (verified by looking at system monitor). I used OpenFoam 1.5-dev with generalized grid interface (GGI, rotor in the mesh).

Given these results my impetus to cluster computers together has died. Haha.