Thursday, December 1, 2011

PoV Yoyo update: v0.1 and failcode (also, Hello World in microcontrollers)

PoV yoyo update:
v0.1: 6 leds (3 pins), attiny45, phototrans, button, isp header (no battery) -- board done.
v0.1 -- code is the fails. I've been chasing this weird compiler bug for many days now.

So I milled and populated my eagle circuit and it works (well, the LEDs at least, haven't tested buttons / phototransistor). https://github.com/nouyang/pov-yoyo and http://fab.cba.mit.edu/classes/4.140/people/nancy.ouyang/Week11/Week11.html



eagle schematic
I'm using the ng.lbr, fab.lbr, and the sparkfun libraries. More info here: http://academy.cba.mit.edu/tutorials/eagle/eagle_resources.html and the list of parts in fab.lbr:
http://fab.cba.mit.edu/about/fab/inv.html
board layout
slightly cleaned up, colors inverted, for milling out on the roland modella in the MIT Media Lab shop. I export at 1000 dpi to be safe, and clean it up in the open-source and free GIMP image editor.
powered off of USB for now. 
The yoyo is 3d printed, but it's designed to be injection molded. I'm working with Laura Shumaker and Dan Fourie, and it's based off of lshu's 2.008 group's yoyo design from last year. I'll upload the Solidworks files when I get permission. Here's what the CAD files look like (there are three parts. The PCB should pressfit inside the inner body, which fits inside the outer body, and the retaining ring goes on top, pressfitting into the outer body and making sure the inner body doesn't come out).
The three parts that I 3d printed

So yea, you can poke the eagle file on github and see that I simply drew a rectangle starting at the origin and then set the x2 and y2 coordinates according to the 2d solidworks measurements. (For more on spatial constraints and pcb layout, see http://orangenarwhals.blogspot.com/2011/11/how-to-design-pcbs-to-fit-cad-models.html)


inner body determines dimensions of board. Corners filleted due to concern over injection molding mold machinability, but turns out to be unwarranted (I think), next version will have sharp corners.

I ended up approximating in Eagle the dimensions from the CAD file that I would need to fit inside the 
After that I devolved into code misery at the down point of which I was wondering why I couldn't even copy code correctly. Turns out to be a makefile issue. See: http://orangenarwhals.blogspot.com/2011/11/crazy-compiler-bugs-avr-studios-avr-gcc.html

Anyway, so now I'm at the point where I can turn each LED on individually, I'm still trying to figure out my code bugs.

Oh right, this is after my realization last week that I don't understand any codes. Not even hello world codes.  0b000? 0x000? 0? char? int? huh?

So, I read up on bit operations stuff -^-^-
I recommend these for explaining the hello world code, which seems straightforward now (turn LED on! turn off!) but seemed completely foreign when I was trying to debug my code / write my own / mash together code from other people.
[1] http://fab.cba.mit.edu/content/tools/microcontrollers/c_for_microcontrollers.html
[2] http://www.arduino.cc/playground/Code/BitMath
[3] http://iamsuhasm.wordpress.com/tutsproj/avr-gcc-tutorial/

My code's here:
https://github.com/nouyang/pov-yoyo
and I'll run over some things I hadn't found clearly explained here.
0x designates hexadecimal, while 0b designates binary. These are fixed flags, similar to a plus or minus sign in front of a number. The actual values that matter come afterward.
So 0b0010 translates to, in decimal, two. And the compiler will assume that there are infinity zeros to the right (well, until 'till the size of the variable or constant at least, eg 0b00000010 for a byte = 8 bits), just as in decimal "2" and "00[...]002" are equivalent.
#define LINE_A 0
#define LINE_B 1
#define LINE_C 2
 
//DDRB direction config for each LED (1 = output) //in or output
const char led_dir[6] = {
  ( 1<<LINE_B | 1<<LINE_A & ~(1<<LINE_C)), //LED 0
  ( 1<<LINE_A | 1<<LINE_B & ~(1<<LINE_C)), //LED 1
  [...]
};
 
//PORTB output config for each LED (1 = High, 0 = Low) //hi or lo
const char led_out[6] = {
  ( 1<<LINE_B & ~(1<<LINE_A)), //LED 0
  [...]
};
What do these lines mean? Well,
1 << LINE_A means 1 << 0 according to the #defines : This means "put a 1 shifted over 0 bits", aka 0b1 or 0b00000001
1 << 1 : 0b10, or 0b00000010
The "|" means bitwise OR, aka I add the two numbers together to get
0b00000011 -- that is, DDRB pins 1 and 2 are both outputs and everything else is in high impedance mode. To be safe, since I am using 6 LEDs on 3 pins
3 Pin Charlieplexing.png
http://en.wikipedia.org/wiki/Charlieplexing for more info
and therefore cannot have uncertainty about whether the unused pin is in high impedance (input) mode or output mode, I explicitly state with
& ~(1<<LINE_C) that pin 7 (on the attiny45, see datasheet which tells me that pin7 corresponds to index 2 on DDRB -- hence #defines LINE_C 2) must be in high impedance mode.
See [1] for an explanation of what & ~(a 1 at the appropriate index)
I'm not certain this is necessary, since in my case I explicitly say "DDRB = 0b011" later in the code rather than saying "DDRB |= 0b011" which would have left high any unspecified pins that were originally high, but I'd rather put it in here than risk wondering if my bugs are because of this.

Thus, an equivalent led_dir array could have said led_dir = {0b001, 0b011, [...]}.

C Resources:
My code 
is based off of:
Charlieplexing code:
Most PoV code appears to be in asm:

No comments:

Post a Comment