Showing posts with label arduino. Show all posts
Showing posts with label arduino. Show all posts

Wednesday, June 19, 2013

Code efficiencies on #Arduino

Let's talk a minute about code efficiency. I’ve written code before for devices that had small memory models and Arduino is no exception. Every spare byte of memory used can be the difference between success or failure. This isn’t a problem with your PC because it employs a virtual memory model. When you open the 20th tab on your web browser and your PC runs out of memory, your PC simply takes some programs that it is not currently working on and the data that they have in memory and writes them to a swap file on your hard disk. When those programs are needed again, something else is removed from memory and they are swapped back in. The user doesn’t, usually, even notice this happens except that their pc will get slower the more that this has to happen, because reading from the hard disk is much slower than reading from memory. So, yes, if you have enough going on that your PC is swapping things in and out constantly, your PC will keep slowing down. That advertisement that has the dollar bills flying from a piggy bank is still running, being swapped in and out, even though you haven’t looked at that web page in 20 minutes. Just close it. 

Anyway, this is handled by your computer’s operating system (OS). This can be Window’s, iOS, Lynix, etc. Your Arduino doesn’t have an OS. It has very little beyond the boot loader and your last uploaded sketch. Even if an OS was written for it, without a hard disk, there’s no where to write a swap file. That’s not to say it couldn’t be done. Some clever person, or group, may write a simple OS that will implement virtual memory using an SD card or something. But, today, as far as I know, that doesn’t exist.

That is why I have to worry about code efficiency. Having said all of that, our “Shooting Star” game is really in danger of running out of memory on my Arduino mega compatible microcontroller which boasts 256KB of flash memory. Only 8KB is used by the bootloader. In times when PCs are talking about gigabytes of memory ¼ of a megabyte seems terribly small, but these sketches are tiny. Since this game is going to be our first complete project, not including experimentation, I would like to build a permanent version with a nice case that my kids can play with and, more importantly, as a keepsake of this milestone of our journey. I have no intention of using the power, and size, of this microcontroller board for this little keepsake. My plan is to spend $3.00 on an ATtiny84 which has 512 Bytes of memory. Yes, Bytes, roughly ½ KB and the bootloader will steal some of that! It’s like comparing a drop of rain to a lake.  Add a 9 volt battery adapter, a little pcb board, power regulator, a bit more resilient push-button, power switch, and a case. Without actually pricing out everything, I suspect that we can put it together for under $25 and a ton of new experiences (flashing bootloaders, pcb layout, soldering, etc.)
ed: I apparently mis-read the specs for the ATtiny84, it can actually have up to 8k of Flash memory.  It has a 512 byte eprom and 512 byte sram.    

So where am I going to find these inefficiencies in my program? Everywhere, you’d be surprised. Let’s start with my displayLed() function. I thought I was being pretty efficient by assuming that only 1 LED would be lit at a time. What I had though was a lot of code:


void displayLed(unsigned long iVal){
  digitalWrite(latchPin, LOW);            //Pull latch LOW to start sending data
  if (iVal > 255){
    shiftOut(dataPin,clockPin,MSBFIRST,0);
    shiftOut(dataPin,clockPin,MSBFIRST,iVal/256);
  }
  else
  {
    shiftOut(dataPin,clockPin,MSBFIRST,iVal);
    shiftOut(dataPin,clockPin,MSBFIRST,0);
  }  
  digitalWrite(latchPin, HIGH);           //Pull latch HIGH to stop sending data
}

As with most discoveries, this was not a Eureka moment. I was thinking, after the “caught” LED blinked, wouldn’t it be nice to have it split and fly off in both directions? By my displayLed() function can’t handle 2 LEDs. Technically, it can, but only in the right 8 LEDs. So I turned to Excel, as I often do, to figure out the math. I had already figured out that the left 8 leds can be calculated by “int(a1/256)” and realized that the right bits are actually the remainder of that calculation “mod(a1,256).” I came up with this using those 2 formulas:
1
0
1
00000000
00000001
2
0
2
00000000
00000010
4
0
4
00000000
00000100
8
0
8
00000000
00001000
16
0
16
00000000
00010000
32
0
32
00000000
00100000
64
0
64
00000000
01000000
128
0
128
00000000
10000000
256
1
0
00000001
00000000
512
2
0
00000010
00000000
1024
4
0
00000100
00000000
2048
8
0
00001000
00000000
4096
16
0
00010000
00000000
8192
32
0
00100000
00000000
16384
64
0
01000000
00000000
32768
128
0
10000000
00000000
If I want the 3rd LED from each end lit, I would add 8192 + 4 getting 01000000 00000010 in binary, but more importantly, I’d get 32 for the left register and 4 for the right register. Now back to the displayLed() function. With the math worked out, I can get rid of 2 lines of code and the entire “if” structure:

void displayLed(unsigned long iVal){
//This will work for 16 leds only and light any value between 0 and 65535
  digitalWrite(latchPin, LOW);         //Pull latch LOW to start sending data
  shiftOut(dataPin,clockPin,MSBFIRST,iVal%256);//Right 8 Leds
  shiftOut(dataPin,clockPin,MSBFIRST,int(iVal/256));//Left 8 Leds
  digitalWrite(latchPin, HIGH);        //Pull latch HIGH to stop sending data
}

I admit, I had to look up modulo, which isn’t a function, but an operator “%”)

Wednesday, May 15, 2013

PWM on the cathode

This is the new circuit. You can see I've added current limiting resisters on the cathode side of the diodes. I used 220k resisters on the blue and green and I wanted 330 for the red but didn't have any that size. I think the next size I had above 220 was 470 which turned out to be either too big or possibly I wired it wrong because I never saw red in my loops. Now that I think about it, it could have just as easily been my code. Also, you may have noticed, I don't have 36 connections. This is because the Arduino Mega doesn't have the 24 PWM pins that I would need to drive the whole board, so I choose to use a 4x4 grid in the center of the board. It does appear to work although there is still a notable flicker.

Tomorrow, I'll debug my circuit and sketch. In the end, I'll still have to wait for the shift registers to arrive to fully test this.

Wednesday, May 8, 2013

Entering the Matrix

No, Keanu Reeves isn't gonna ask you to pick the Red or Blue pill. This is the Matrix, Arduino style. Today, the new breadboard arrived. As I suspected, the LED matrix will not fit. But between the two breadboards, I should be able to make this work. I've already wired pins 17-32 on the mini breadboard and have the LED matrix mounted between both boards. To late to play any more tonight. I'll have to finish running the remaining wires tomorrow. I'll post a picture too.

Wish the servo would get here soon...

Saturday, May 4, 2013

More Parts Arrive...

Next, the connector wires and the breadboard arrived. The connector wires are cool. Each wire rather than being solid wire or dipped in solder, are attached to a pin connector, plus all 40 wires are molded together like a ribbon cable, yet easily pulled apart.

But the breadboard...
Oops! when the description said "mini," it wasn't kidding. Note to self, "measure first, then order." There is no possible way to do anything with the diode matrix.

In the meantime, some basics for the kids. We talked about current and how if flows from one end of the power source, in this case a battery, through the circuit and back to the battery. We talked about diodes, since this is the first thing we would be utilizing. We especially talked about the fact that they will only allow the current to pass through in one direction.
To drive the point home we did a little experimenting with the Snap Circuits kit that my son got for Christmas. This includes some basic parts like a motor, 3 ICs, an LED, speaker, 2 types of switches, etc. We assembled a basic circuit that had a push-button to turn on the LED. Next, we replaced the LED with a light bulb. To make a point we turned the light bulb around and it still lit when we pushed the button. Then we put the LED back correctly, proved that it worked, then turned it around too. No light emitted when the button was pushed.

The Snap Circuit parts are really clever. First, they do have a genuine snap, like a winter coat would use, on the connection points of each part. Second, they have the schematic representation of the part on it. Now that they saw this, we could talk, at length, about the, much more complex, schematic for the LED array.

But, we still really wanted to get building something, anything, using the Arduino board. I found some LED replacement bulbs that belonged to set of Christmas lights that we had bought. 3 white LEDs, that's it. I took one of the LEDs out of it's plastic housing and placed the long wire (anode or positive) in pin 13 and the other wire (cathode or negative) went into GND (ground) right next to it. We powered up the board and the new LED blinked in time with the on-board LED since our sketch from last time was still on there. Next, I thought we could move the LED to another pin, and modify the sketch to alternately blink the on-board LED then the one that we just moved to pin 10. Just as a quick test, I changed the sketch to just blink pin 10 instead of 13, by changing the led variable to 10. Now, for the record, the anode is in 10 and the cathode is in 9. Compiled, downloaded, nothing. No lights blinked anywhere.

Times up, I have to figure out what to do about the ground. Yeah, I can move the LED to my teeny, tiny, breadboard and have the anode go to pin 10 and the cathode go to ground and all would be right with the world and the sketch. But, there is something that I'm missing...