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:
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:
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 }
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 }