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.

Thursday, November 10, 2011

Long time, no post: CFD and Carbon Fiber Prototyping

It's not that I have been on a project hiatus, I have been hard at work with CFD simulations, researching a possible invention! So I do not want to post everything I have done just yet. But I will be posting the physical prototype I have referred to in a past post, made of water-jet-cut aluminum plate, driven by a ~600W brushless motor. It was made to validate CFD cases, and I gained some insight from it. I have also made a YouTube video of my first FanWing CFD case public. It was done a long while ago.



I have been working on clustering computers, that is connecting by ethernet cable more than one desktop together and using their processors to work on one case together. I am doing it on Ubuntu 10.04LTS and using OpenFOAM 1.5-dev. I will have results shortly. Useful link: Clustering computers

I am now investigating building carbon fiber models, and I will see if I can do myself rather than have a prototyping service do it.

Friday, February 18, 2011

Easy pulse width modulation (PWM) with PICs to control brushless motor ESCs, servos, and other things

Today I present a brushless motor controlled by an electronic speed controller (ESC) and a PIC microcontroller. The PIC microcontroller performs the function of a R/C reciever by taking in a signal (here generated by a pot) and outputting the appropriate signal (here a PWM square wave) for the ESC to use to determine the rotation speed of the brushless motor.



Simple background: this brushless motor was bought at Hobbyking for less than $20 and can put out something like 600W. Although that is pretty high, it is not to be used for wheeled vehicles, which have highly dynamic loads and high current spikes. These brushless motors are intended for R/C planes' propellers, which have very steady and predictable loads. I have it connected to an electronic speed controller (ESC), which I bought, that dishes out the current at the right times to the brushless motor based on a simple pulse-width modulated signal it receives. The ESC is necessary because brushless motors operate in a totally different way from DC motors. Brushless motors are 3-phase, and as a result have three wires that need to be connected to a power source. Where you could just apply a steady voltage to DC motor and the commutator takes care of current alternation, brushless motors require more deliberate control. This control is not the subject of this post. I use a PIC to easily create and control a PWM signal using PIC's onboard timers for the ESC to interpret. So this post is basically about programming PICs specifically, to generate a PWM signal, of any flavor or kind if you like.

The signal generated here is a standard servo signal of 50 Hz (period 20 ms) with a square wave pulse that ranges in width from 1 to 2 ms.

What the software does: The software uses PIC's Timer1 and Timer0 and interrupts to make the signal, whose length varies (of the signal that can vary from 1 to 2 ms, the 50 Hz cycle is fixed) based on an analog input from a potentiometer. The PIC is constantly polling and converting the signal from a potentiometer to a value from 0 to 255, while in the background the Timers are counting down. Timer1 has a fixed time length (of course defined by me) of 20 ms, and Timer0 has a length from 1 ms to 2 ms, determined by the ADC. Timer1 dictates when the pulse, whose length is determined by Timer0, occurs. Notice that every cycle there is at least a period of 18 ms where the signal is low. The timers counting down and the potentiometer signal polling occurs simultaneously. When the Timers countdown, interrupts stop the PIC from whatever it was doing, executes a specified procedure, and then the PIC resumes whatever it was doing. In this case, the interrupts would be used to stop and start signals.

The c code:
//Using default Internal Clock of 4 Mhz
//To use TMR1 at 50 Hz and 1:1 prescaler, set offset to 45535.
//TMR0 can vary from 7 to 132, or 2 ms to 1 ms, at 1:1 prescaler.
//Use TMR0 to control pulse width, even though TMR1 has much higher resolution, because TMR1 offset is 16 bits and may require lots of time to compute proper TMR1 offset from ADC value.

#include
__CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
& UNPROTECT & BORDIS & IESODIS & FCMDIS);

unsigned int pulse = 0;

//Interrupt function
static void interrupt isr(void)
{
if(T0IF)
{
RC0 = 0;
}
if(TMR1IF)
{
TMR1IF = 0;
//Start 50 Hz cycle period.
TMR1L = 0b11011111;
TMR1H = 0b10110001;
//Turn on variable pulse.
RC0 = 1;
if(RC1 == 1) //safety switch (must be pressed).
{
TMR0 = pulse;
T0IF = 0;
}
else //off.
{
TMR0 = 132;
T0IF = 0;
}
}
}

void main(void)
{
//Setting ports.
TRISA = 0x00001001; // Set A0 (for ADC) and A3 (MCLR) to input, others output
PORTA = 0x00;
TRISC = 0b00000010; //Set C1 to input for safety on switch.
PORTC = 0x00;
//ADC configuration.
ADCON1 = 0x00;//So that ADC conversion clock is set to Fosc/2.
ADCON0 = 0b00000001;//ADC enabled.
ANSEL = 0x01; // Set A0 to analog, others digital

//Timer configuration
OPTION = 0b00000010; // Timer0 configuration, 1:8 prescaler.
TMR1L = 0b11011111;
TMR1H = 0b10110001;
T1CON = 0b00000001; // Timer1 configuration, including 1:1 Prescaler and TMR1ON = 1.

//Timer interrupt enabling.
T0IE = 1;
TMR1IE = 1; // Timer1 interrupt enable, needed with PEIE and GIE bits set.
PEIE = 1; // Peripheral interrupt enable, for Timer1.

//General interrupt enabling.
GIE = 1; // Global interrupt enable, for Timer1 and Timer0.

while(1)
{
GODONE=1; // initiate conversion.
while(GODONE) continue; // Wait for conversion to finish.
pulse = 7+ADRESH*125/255;
}
}


The c code is turned into a hex file via MPLAB and I program the microcontroller with the PICKit 2. The microcontroller is a PIC16F690. Analog-to-digital conversion signal (from potentiometer) input is at A0 and ouput PWM signal is at C0. There is an input at C1 for a momentary pushbutton, which needs to be held in order for an input at C1 to be high. This is for safety, as I want it to be easy to turn the motor off by just letting go of the pushbutton. So no matter how high a speed the potentiometer is set to, nothing will happen unless the pushbutton is held.

Since the ADC gives values from 0 to 255, the resolution, or how many speed levels, you have is limited to 256. So it does not matter whether you use Timer0 or Timer1 for determining the signal length (Timer1 has a much higher temporal resolution). I use Timer0 because it probably takes less time for the PIC to do the arithmetic of converting the ADC value to the appropriate number. Timer0 uses 8 bits to define counter number (up to 255 in decimal), while Timer1 uses 16 bits (up to 65535 in decimal).

Remember, when using PICs as standalone portable devices, two things should be done: there should be a capacitor across the power supply pins (here, .1 microFarad, and yes this is absolutely necessary, else the PIC just keeps turning off and on) and a resistor tying MCLR pin to the power supply (here 10 kOhm). Also, I tied the input C1 pin to ground, so that electrical noise wont make it go high and low unintentionally.

Wednesday, February 16, 2011

Putting together a prototype/validation for CFD...

This is my second foray into building something mechanical, my previous venture utilizing only junkyard parts to build a testing platform for something similar to the Fanwing last summer (this is before I even touched CFD, and is incidentally why I picked up CFD). It ended up weighing 80 pounds, using a 5hp motor I had used in 8th grade to power a massive, hot roller mill for making rubber bands for a science fair project (10+ ingredient chemical recipes, fun times) and v-belt transmission for a cross-flow-fan test section of about a foot in diameter and less than 2 feet in span (picture of it here maybe if i remember). I guess it ended up not being very useful, but for the amount of metal-working and welding I had to do, I have at least a modicum of pride in it.

Anyways this time I used all of the internets to find non-junkyard parts for use in conjunction with a water jet cutter, which is awesome and I now have access to, to build a prototype for CFD validation. The design in Autodesk Inventor (which, unlike SolidEdge ST3, allows easy use and integration of variables for dimensions so you do not have to redo your whole design if you need changes in a few parts) looks very tight and I am excited to build it.

Anyways, I always post to share something that I think may be useful. For this post, it is some vendors in case you are planning to build something:
Main vendors:
- McMaster-Carr (Everything mechanical)
- Hobby King (Motors, batteries, etc.)
Places that had stuff that the main vendors did not have:
- SDP SI (Has a whole lot of mechanical stuff, but I used them for their extensive variety of timing belt pulleys)
- Fastenal (For 4-40 square nuts, and if you do not want to buy set screws or square nuts, etc. by the 100's or more)
- Digikey (Angle brackets; usually an electronics supplier; I bought PIC microcontrollers from these guys before; Use google to search their stuff)

Although this post feels pretty unsubstantial, it is but the calm before the storm of substance, if you will. I will be posting more about my mechatronic CFD validation, uhh... machine.

Tuesday, January 25, 2011

Hyperthreading and CFD

So I just performed a little experiment testing effect of Intel's "hyperthreading" (HT) technology on CFD solver speed. HT, or as some have called it, "hype threading", increases multitasking performance by trying to more efficiently allocate processor resources. One HT core is seen as two cores by the computer.

So I would expect that CFD solver speed would not benefit from HT, as opposed to disabling HT. My computer contains an i7 2600, a four-core processor. I decomposed the HT off case into four domains (one for each core), and of course I decomposed the HT On case into eight domains (one for each virtual core). The usage of all of the processors at 100% and that the right number of cores was perceived by the OS was verified by checking Ubuntu's System Monitor application. HT was enabled and disabled in BIOS.

In OpenFOAM, running the same exact case, the run times for HT on and off were:
HT On (8 virtual cores): 0.0692875 simulation seconds in 6213 real-life seconds.
HT Off (4 cores): 0.0692822 simulation seconds in 5154 real-life seconds.

So, as expected, HT does not give performance gain, but in fact imparts performance loss. We should expect similar performance because it is the same hardware, and computational efficiency usually decreases on a per-core basis with more cores (time is wasted in inter-core communication, etc.). Also, we see that the processor performs as expected (as four normal cores) with HT disabled.

Of course, I am not saying anything about HT's usefulness for multitasking, which is what it was designed for.

Thursday, January 20, 2011

PIC servo control with ADC Input

I have not used PIC in a long while, as it has been replaced by the Arduino. The reasons are that I have to program the PIC at a lower level of abstraction, the PIC does not have all of the built-in convenient functionality of the Arduino, and the PIC is harder to debug.

Even so, I have programmed a servo controller with a PIC that takes in an analog value from the Arduino (via PWM, a rectifier capacitor can be placed), and translates this to a 50 Hz PWM servo signal with pulse widths ranging from 0.6 ms to 2.4 ms for the control of a HS-311 servo. If your servo requires different pulse lengths it is easy to change in the code.

The reasons for making a PIC servo controller are two:
-The PIC is much cheaper. Ordering from Microchip I can get the PIC16F690 for less than $2 a piece.
-The Arduino servo library control gets messed up when you change the timer settings. On the same Arduino I wanted to control the servos, I changed the timers so that the PWM operates at above 30 kHz.

I programmed a PIC16F690 using PicKit 2 (there is now a newer PicKit 3) and the free MPLAB IDE using the also-free HITECH compiler.

The software utilizes Timer 0 for the 50 Hz signal refresh rate and Timer 1 for the pulse length. This was done because a higher resolution of pulse width was achieved with Timer 1. Several very useful calculators for finding the Timer offset value settings to correspond to the desired times can be found by Google searching 'PIC timer calculator'. I have one that I got a few years back, but I cannot seem to find it now; maybe it updated.

Friday, January 7, 2011

The manual wire wrap tool: a microelectronics hobbyist's best friend for solderless connections

Tired of soldering? Tired of breathing in potentially toxic fumes? Then the wire wrap is just for you. Look it up on Google for pics and how to use it (and where to buy!). It's awesome. I just discovered it. It allows you to effortlessly strip and coil thin wire (I was using 30 gauge, for PIC pin outputs) tightly around a thicker pin (DIP extensions, those common square-cross-sectioned headers, etc.). Surprisingly (to me) strong in tension; could not pull it off without breaking whatever it was attached to first. If you venture away from PCB boards, this is a must have, especially since it is a simple and cheap tool.

Thursday, January 6, 2011

For those who want to start CFD (Computational Fluid Dynamics) simulations...

I started CFD in OpenFOAM with no prior experience in CFD. I did not even have the Navier-Stokes equations memorized or anything. Do not write it off as impossible without even trying, as I had.

A quick and useful introduction to CFD in general is available here.

Once you have some grasp of what CFD is about, you can move onto installing and using CFD programs. A great resource for all steps of the whole simulation process is CFD-online. This website was essential for enabling me to run my own simulations.

I would love to elaborate on whatever you cannot find in the two resources I described above. Please comment if you have any questions at all, and I will be sure to reply in a short time.

Wednesday, January 5, 2011

Correctly using PIC in a device disconnected from the PicKit/computer

So I was trying to switch transistors with outputs from the PIC pins, for a project I will post probably tomorrow. The output voltage (digital I/O) was like .6 V when the PIC was running on a 4.5 V source. All that was needed was to tie the MCLR pin high (I used a 15k Ohm resistor). The pin voltage then went to 2.8 V, which was sufficiently high to finally bias the transistor base. I do not know why it is not equal to 4.5 V, but I do not really care presently (EDIT: Ah, it was just a software error). So for basic functionality for a PIC used on a standalone circuit (i.e. taking it off a PicKit dev board), you just need a .1uF capacitor across power supply anode and cathode and the MCLR pin tied high.

Of course, you could just disable MCLR. However my c code compiler for PIC (PICC Lite) does not recognize the bit as MCLRE, or the CONFIG register. So... if you know put it in the comments please.