Pages: 1 [2] 3 4 ... 16   Go Down
Author Topic: core13: An Arduino core for the Attiny13 *testers wanted*  (Read 41063 times)
0 Members and 2 Guests are viewing this topic.
Washington
Offline Offline
God Member
*****
Karma: 38
Posts: 790
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry but the attiny 13 nave only 1 k of flash , and only the sketch blink is 1.2k , what worldwide you do whit the attiny 13 ?, thanks for the core
Not sure what is going on here.
The standard blink sketch compiles to 370 bytes with my core.
Even with the standard Arduino core its a bit less then 1KB.
Which blink sketch, compiler, etc? Blink should certainly not be over 1KB.
@ElectroNick
You can most likely use a byte for "j" and operations on a byte may be slightly smaller
I also guess there is a better way to do this
Code:
if(j>8)
  { d=false;
  }else if(j<1)
  { d=true;}
  if(d){j++;}else{j--;}
but I cannot think very well right now.
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Offline Offline
Full Member
***
Karma: 0
Posts: 182
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Excusme for my english but i'm italian, now i understand how your core work , it's vero interesting , at the moment i haven't some attiny 13 but i'll test the core when i can , Thanks you vero much for this core
Niko
Logged

Non possiamo pretendere che le cose cambino, se continuiamo a fare le stesse cose(albert Einstein )

Pennsylvania, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 31
Trying to make sense of it all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

smeezekitty, I seem to have hit a brick wall here  smiley-sad-blue, wonder if you have a few pointers for me.

delay() function seems to be acting up: if you call it as delay(500);, it works as expected. But if you're calling it as delay(someVariable); , the program just stops and sits there indefinitely.  I've tried passing it int, long and byte  type variables (in my case, looked up values from an array defined as either of those types) and it hangs on all of them except when you literally just type the value in ( i.e. delay(500); ).

I'm trying to modify my own light chaser sketch (code below) to include a sort of a pseudo-PWM brightness control. It compiles fine but when executed, the LED matrix sits dark. If you type in, say delay(100) instead of delay(onDelay) and do the same for delay(offDelay), the LEDs work but of course, the gradual brightness increase does not happen.

It's a rather simple change to an already working code and I just can't wrap my head around the issue. That's why the question about the delay() implementation came up. Any critique or tips would be appreciated.

Cheers!

Code:
int j; // just a counter
boolean d; // direction forward=true
byte bitmap[]={B00000001,B00000010,B00000001,B00000100,B00000001,B00001000,B00000010,B00000100,B00000010,B00001000};
byte outModes[]={B00000011,B00000011,B00000101,B00000101,B00001001,B00001001,B00000110,B00000110,B00001010,B00001010};
//byte waveforms[16] = {1,4,15,31,50,69,85,96,100,96,85,69,50,31,15,4}; // happens to be 1/2 of sine wave. Just for test - some other profile may look better.
int waves[]={25,50,100,50,25}; // even simpler waveform
int cycleDelay=100;

void setup() {
d=true;
}

void loop() {
 
 byte outModeNow =  outModes[j] ;
  byte bitmapNow=bitmap[j];
  if(j>8)
  { d=false;
  }else if(j<1)
  { d=true;}
  if(d){j++;}else{j--;}

  for(int x=0; x<5; x++){ // counter for the waveform
      int onDelay = waves[x];
      int offDelay = cycleDelay - onDelay;
     
      DDRB = outModeNow;
      PORTB = bitmapNow; // turn LED on
      delay(onDelay);   // then wait
      DDRB = B00000000; // turn everything off
      delay(offDelay); // wait for the off period
  }

}

Logged


 /\_/\      ARDUINO
((@v@))     CNC
()~|~()

Washington
Offline Offline
God Member
*****
Karma: 38
Posts: 790
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

smeezekitty, I seem to have hit a brick wall here  smiley-sad-blue, wonder if you have a few pointers for me.

delay() function seems to be acting up: if you call it as delay(500);, it works as expected. But if you're calling it as delay(someVariable); , the program just stops and sits there indefinitely.  I've tried passing it int, long and byte  type variables (in my case, looked up values from an array defined as either of those types) and it hangs on all of them except when you literally just type the value in ( i.e. delay(500); ).

I'm trying to modify my own light chaser sketch (code below) to include a sort of a pseudo-PWM brightness control. It compiles fine but when executed, the LED matrix sits dark. If you type in, say delay(100) instead of delay(onDelay) and do the same for delay(offDelay), the LEDs work but of course, the gradual brightness increase does not happen.

It's a rather simple change to an already working code and I just can't wrap my head around the issue. That's why the question about the delay() implementation came up. Any critique or tips would be appreciated.

Cheers!

Code:
int j; // just a counter
boolean d; // direction forward=true
byte bitmap[]={B00000001,B00000010,B00000001,B00000100,B00000001,B00001000,B00000010,B00000100,B00000010,B00001000};
byte outModes[]={B00000011,B00000011,B00000101,B00000101,B00001001,B00001001,B00000110,B00000110,B00001010,B00001010};
//byte waveforms[16] = {1,4,15,31,50,69,85,96,100,96,85,69,50,31,15,4}; // happens to be 1/2 of sine wave. Just for test - some other profile may look better.
int waves[]={25,50,100,50,25}; // even simpler waveform
int cycleDelay=100;

void setup() {
d=true;
}

void loop() {
  
 byte outModeNow =  outModes[j] ;
  byte bitmapNow=bitmap[j];
  if(j>8)
  { d=false;
  }else if(j<1)
  { d=true;}
  if(d){j++;}else{j--;}

  for(int x=0; x<5; x++){ // counter for the waveform
      int onDelay = waves[x];
      int offDelay = cycleDelay - onDelay;
      
      DDRB = outModeNow;
      PORTB = bitmapNow; // turn LED on
      delay(onDelay);   // then wait
      DDRB = B00000000; // turn everything off
      delay(offDelay); // wait for the off period
  }

}

T
he code you provided did not compile. I had to change all the Bxxxxxxxx values to 0Bxxxxxxxx format (added 0 prefix).
But after making that change, it seemed to work but I did not have to proper LED array hooked up to test it fully.
I also tested the delay in another test program and again it works with no problems with variable values.
Either there is a problem with Arduino IDE 1.0 or clock speeds other then 128khz.
I may have to break down and try IDE version 1.0.


Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Pennsylvania, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 31
Trying to make sense of it all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think I got the issue down to the ATtiny13 hardware limitation - with only 64 bytes of SRAM you really have to be very careful with sizes of the variables  and arrays. I think the problem with my code was that the RAM would fill up really quickly.

I've tried to remove everything I could and had to do linear brightness increase, which isn't really a very attractive option  smiley-small I had to strip almost everything down (eliminate variables unless absolutely necessary, reduce int to byte where possible and so on) in order to get it to work and I had to give up trying to control the brightness with sine and other complex waveforms - the only way I could do it was to go 0-100% in the first quarter of the cycle and  hold it for the rest of the cycle. The effect of the gradual brightness increase is almost imperceptible, but that was the best I could do. Hope someone could come up with a better code!
Here is it:

Code:
/*
  Charlieplexing example for ATtiny13 with some brightness control using pseudo-PWM
  This code is for a 10-LED bargraph display. You can increase the amount of LEDs controller by the Tiny to 20 if needed.
  Code by Elabz.com
  http://elabz.com/
  This example code is in the public domain. If you end up using it in a project, please drop me a message, I'd be happy to
  know it was of some use. I'll also be happy to feature your project on my site, so send some pictures, too.
 
  LED hookup can be gleaned from the bitmap[] array values. For example, first LED's value is B00000001 which means that
  to light the LED the D0 has to ho HIGH and D1 - LOW, so the LED's anode is facing D0. LED #2 is between the same legs but in reverse.
  LED #3 is between D0 and D2, LED #4 is the same legs but in reverse and so on.
 
//       ATMEL ATTINY13 / ARDUINO
//
//                 +-\/-+
// ADC0 (D 5) PB5 1|    |8 Vcc
// ADC3 (D 3) PB3 2|    |7 PB2 (D 2) ADC1
// ADC2 (D 4) PB4 3|    |6 PB1 (D 1) PWM1
//            GND 4|    |5 PB0 (D 0) PWM0
//                 +----+

 
 
 */
byte bitmap[]={0B00000001,0B00000010,0B00000001,0B00000100,0B00000001,0B00001000,0B00000010,0B00000100,0B00000010,0B00001000};
byte outModes[]={0B00000011,0B00000011,0B00000101,0B00000101,0B00001001,0B00001001,0B00000110,0B00000110,0B00001010,0B00001010};
boolean d; // direction forward=true
byte j=0; // just a counter
long periodPWM;
long periodNow;
int cycleDelay=3000;
void setup() {
periodPWM = cycleDelay/200;
d=true;
}

void loop() {
int offDelay;

  for(byte x=0; x<50; x++){ // counter for the waveform
      offDelay = 50 - x;
      periodNow = millis();
     
      while(millis()-periodNow < periodPWM)
      {
      DDRB = 0B00000000; // turn everything off
      delayMicroseconds(offDelay); // wait for the off period
      DDRB = outModes[j];
      PORTB = bitmap[j]; // turn LED on
      delayMicroseconds(x);   // then wait
     }
  }
delay(cycleDelay*3/4);

  if(j>8)
  { d=false;
  }else if(j<1)
  { d=true;}
  if(d){j++;}else{j--;}
 
}
 
Logged


 /\_/\      ARDUINO
((@v@))     CNC
()~|~()

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 207
Posts: 12903
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


The correct datatype is unsigned...
unsigned long periodPWM;
unsigned long periodNow;


cycleDelay is a constant and should be declared as such...
const int cycleDelay=3000;

bitmap is not only constant but it is a perfect candidate for PROGMEM which will free some SRAM.

outModes is not only constant but it is a perfect candidate for PROGMEM which will free some SRAM.

periodNow does not need to be global.  Making it local will free 4 bytes of SRAM.

offDelay is too large of a datatype.  Make it byte.

offDelay does not need to be global.  Make it a local variable.

periodNow and periodPWM can both be reduced to a 16 bit datatype.

Initializing d should knock one machine instruction out of Flash...
boolean d = true; // direction forward=true
void setup() {
...
d=true;
Logged

Washington
Offline Offline
God Member
*****
Karma: 38
Posts: 790
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bitmap is not only constant but it is a perfect candidate for PROGMEM which will free some SRAM.

outModes is not only constant but it is a perfect candidate for PROGMEM which will free some SRAM.
I thought the same thing.
For more information about progmem see:
www.nongnu.org/avr-libc/user-manual/pgmspace.html
http://arduino.cc/en/Reference/PROGMEM
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Pennsylvania, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 31
Trying to make sense of it all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@Coding Badly, smeezekitty:
guys, thank you very much for the tip! Moving the arrays with constant values to Flash using PROGMEM did the trick! I'm happily perusing relatively complex waveforms now like 48-values sine and there's room for more if 48 is too coarse for your application). 

I'll dress the code up a little and post it later. Maybe even finally get the schematics done - I understand that charlieplexing code can be really difficult to read without looking at the schematics because so much depends on how the LEDs are connected.

Thanks again for the tips and the nice core: I now have another tool on my belt! (well, OK, chain  smiley-grin )

Cheers!
Logged


 /\_/\      ARDUINO
((@v@))     CNC
()~|~()

Pennsylvania, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 31
Trying to make sense of it all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I played some more with my ATtiny running the charlieplexing code trying to make it work from a 3V battery. If I understood the datasheet correctly, it should be able to work all the way down to 1.8V if the clock speed is below 1MHz. So I thought if I make use of the internal 128kHz oscillator, I should be fine.

Not so fast! (pun intended)  smiley-wink

First of all, it was a rather dumb idea to begin with because the code depends very much on the delayMicroseconds() function and it ain't gonna be no microseconds if the internal clock is running at 128kHz, then gets divided by 8 (by default).  There's also a clock prescaler that further divides it by 8? I have to admit, I'm scraping the bottom of the barrel of my understanding of the hardware and it was a rather small barrel to begin with smiley  So, is it then running at a whopping 2kHz clock speed if the suggested 0x7B low fuse is used?

Anyhow, it looks like the timer with 128kHz internal oscillator gets severely off, maybe because I was trying to make it run the above mentioned delayMicroseconds() command several thousand times per second and it just did not have enough clocks in the second to actually do that?

In addition to the timer issues that I'm still struggling with (if I use anything other than the default 9.6MHz osc., 1/8 clock prescaler it ships with) , there's a less obvious issue with 128kHz clock. Once you burn the fuse for 128kHz, you lose communication to the chip! This is pretty scary, especially if you are not prepared (and I wasn't smiley ). The programmer is now running too fast for the chip to respond during ICSP programming and it pretty much plays dead. I did not see it mentioned here, and it may not be a feature of the IDE 0022 that smeezekitty tested with, but for IDE 1.0 I think the boards.txt record has to be changed (changes lifted from the other ATtiny core):

Code:
###########################################################################

attiny13.name=Attiny13 @ 128 KHz (internal watchdog oscillator)
attiny13.upload.using=arduino:arduinoisp
# attiny13.upload.protocol=avrispv2
attiny13.upload.maximum_size=1024
attiny13.upload.speed=250
attiny13.bootloader.low_fuses=0x7B
attiny13.bootloader.high_fuses=0xFF
attiny13.bootloader.unlock_bits=0x3F
attiny13.bootloader.lock_bits=0x3F
attiny13.build.mcu=attiny13
attiny13.build.f_cpu=128000
attiny13.build.core=core13
###############################################################

note the attiny13.upload.speed=250 line - that should slow the programmer down enough.

Anyhow, getting back to the top of this post: I only messed with 128kHz trying to bring the Vcc down to 3V, and failed, even at 128kHz (never mind that the program did not run as expected because of timer issues anyhow). It only works from 5V supply.

Does anyone have any suggestions on how to make this chip run from a lower voltage? Oh, and I neglected to mention before: all ATtiny13 chips I have are labeled ATTINY13 20PU  - so are they ATtiny13 or ATtiny13A or does it even matter for the voltage supply?

Thanks!
 


Logged


 /\_/\      ARDUINO
((@v@))     CNC
()~|~()

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 207
Posts: 12903
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If I understood the datasheet correctly, it should be able to work all the way down to 1.8V...

Only if you have an ATtiny13V or ATtiny13A.  If you have a processor with no A or V in the model number then the minimum voltage is 2.7.

Which model do you have?
Logged

Washington
Offline Offline
God Member
*****
Karma: 38
Posts: 790
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I played some more with my ATtiny running the charlieplexing code trying to make it work from a 3V battery. If I understood the datasheet correctly, it should be able to work all the way down to 1.8V if the clock speed is below 1MHz. So I thought if I make use of the internal 128kHz oscillator, I should be fine.
This is correct.
In fact I can run it down to 1.3V.
[/quote]
First of all, it was a rather dumb idea to begin with because the code depends very much on the delayMicroseconds() function and it ain't gonna be no microseconds if the internal clock is running at 128kHz, then gets divided by 8 (by default).  There's also a clock prescaler that further divides it by 8? I have to admit, I'm scraping the bottom of the barrel of my understanding of the hardware and it was a rather small barrel to begin with smiley  So, is it then running at a whopping 2kHz clock speed if the suggested 0x7B low fuse is used?
[/quote]
Not exactly.
With 0x7B fuse, the prescaler is off.
Furthermore, the core does not make use of the prescaler either. So the the clock is actually 128khz (actually anywhere from 100khz to 140khz).
For my perticular projects, the 128khz oscillator is highly desirable.
Quote
Anyhow, it looks like the timer with 128kHz internal oscillator gets severely off, maybe because I was trying to make it run the above mentioned delayMicroseconds() command several thousand times per second and it just did not have enough clocks in the second to actually do that?
Function overhead becomes a large issue on slow clock speeds. Even with the 1 MHz oscillator this can be a problem.
If you are using fixed values, you can use the _delay_us() function which is faster but is very large if you pass a variable parameter
Quote
In addition to the timer issues that I'm still struggling with (if I use anything other than the default 9.6MHz osc., 1/8 clock prescaler it ships with) , there's a less obvious issue with 128kHz clock. Once you burn the fuse for 128kHz, you lose communication to the chip! This is pretty scary, especially if you are not prepared (and I wasn't smiley ). The programmer is now running too fast for the chip to respond during ICSP programming and it pretty much plays dead. I did not see it mentioned here, and it may not be a feature of the IDE 0022 that smeezekitty tested with, but for IDE 1.0 I think the boards.txt record has to be changed (changes lifted from the other ATtiny core):

Code:
###########################################################################

attiny13.name=Attiny13 @ 128 KHz (internal watchdog oscillator)
attiny13.upload.using=arduino:arduinoisp
# attiny13.upload.protocol=avrispv2
attiny13.upload.maximum_size=1024
attiny13.upload.speed=250
attiny13.bootloader.low_fuses=0x7B
attiny13.bootloader.high_fuses=0xFF
attiny13.bootloader.unlock_bits=0x3F
attiny13.bootloader.lock_bits=0x3F
attiny13.build.mcu=attiny13
attiny13.build.f_cpu=128000
attiny13.build.core=core13
###############################################################

note the attiny13.upload.speed=250 line - that should slow the programmer down enough.
Many programmers are buggy and do not correctly implement slow SCK.
This is the fault of the programmer.
There is a Arduino ISP sketch that I wrote that correctly implements slow SCK that I use for programming my slow chips.
I will try to find the link in a few min.
Quote
Anyhow, getting back to the top of this post: I only messed with 128kHz trying to bring the Vcc down to 3V, and failed, even at 128kHz (never mind that the program did not run as expected because of timer issues anyhow). It only works from 5V supply.
I had no problem going down to 1.8 or even 1.3v.
Maybe the LEDs need higher voltage?
[/quote]
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Pennsylvania, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 31
Trying to make sense of it all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Only if you have an ATtiny13V or ATtiny13A.  If you have a processor with no A or V in the model number then the minimum voltage is 2.7.

Which model do you have?


@Coding Badly: Mine's labeled ATTINY13 20PU, so I guess it's not an "A" after all. Still should work from a 3V battery, no?

@smeezekitty:
 thanks for your input, I guess I got all confused with the combination of clocks and prescalers. It appears that all the way down to 128K may not work for my application anyway, but it's great to know that there's still ways to go in terms of lowering power consumption if the application allows for such slow speeds.

I've seen 1MHz and I believe 4MHz settings in your wiring.c file - what fuse settings would get me there? I've tried various combinations (all internal oscillators though - 128kHz, 9.6MHz and 4.8MHz) but none comes up to the exact figures in the wiring.c codes. How would it have to be changed in order to run properly at the speeds produced by internal  clocks? I think it would be important for wider acceptance of your cores because such a small part will probably be used without an external Xtal most of the time.

As far as the programming speed, I only tried AVRISP mkII so far and, when it knows to slow down, it talks to the chip fine.  So I would not call it a bug as much as it is just a necessary setting for comms with an MCU running at 128kHz internal clock.
I've reviewed my last night's notes and it looks like I've been burning it with 0x6B fuse, not 0x7B. That might explain why the timing was way off. I have to admit, once I realized that I won't get correct operation due to the use of delayMicroseconds(), I just went back to 9.6MHz and did not investigate further.
Logged


 /\_/\      ARDUINO
((@v@))     CNC
()~|~()

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 207
Posts: 12903
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
@Coding Badly: Mine's labeled ATTINY13 20PU, so I guess it's not an "A" after all. Still should work from a 3V battery, no?

You should be fine.

The specifications are essentially guarantees.  Atmel guarantees that your processor works correctly at 2.7 volts / 4 MHz.  If the voltage is lowered or the frequency is increased, Atmel no longer guarantees correct operation.  In practical terms that means the more you exceed the limits the more likely the processor will not work correctly.

For all three models, the maximum guaranteed processor speed is 4 MHz at the minimum voltage (2.7 volts in your case, 1.8 volts for the other two).
Logged

Washington
Offline Offline
God Member
*****
Karma: 38
Posts: 790
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset



@smeezekitty:
 thanks for your input, I guess I got all confused with the combination of clocks and prescalers. It appears that all the way down to 128K may not work for my application anyway, but it's great to know that there's still ways to go in terms of lowering power consumption if the application allows for such slow speeds.
I am not sure about the newest version of your code but it seems alittle in-precession may not make much difference in operation.
PWM is usually somewhat uncritical.
Quote
I've seen 1MHz and I believe 4MHz settings in your wiring.c file - what fuse settings would get me there? I've tried various combinations (all internal oscillators though - 128kHz, 9.6MHz and 4.8MHz) but none comes up to the exact figures in the wiring.c codes. How would it have to be changed in order to run properly at the speeds produced by internal  clocks? I think it would be important for wider acceptance of your cores because such a small part will probably be used without an external Xtal most of the time.
4 and 4.8mhz are not supported yet. I may work on that today.
As far as the internal oscillators support, 9.6Mhz currently uses the 8Mhz code.
For millis() I will probably add the proper division to increase accuracy.
The delay() code is conphensated inside avr-libc and nothing needs to be done.
For delayMilliseconds(), it uses a binary shift to multiply by 2. It actuality, it would need to be multiply by 2.4.
The problem is, multiplying by 2.4 would be significantly slower then shifting left by one.
The error is about 20%. I cannot really fix it very easily without risking making the error worse with calculation time.
Quote
As far as the programming speed, I only tried AVRISP mkII so far and, when it knows to slow down, it talks to the chip fine.  So I would not call it a bug as much as it is just a necessary setting for comms with an MCU running at 128kHz internal clock.
I've reviewed my last night's notes and it looks like I've been burning it with 0x6B fuse, not 0x7B. That might explain why the timing was way off. I have to admit, once I realized that I won't get correct operation due to the use of delayMicroseconds(), I just went back to 9.6MHz and did not investigate further.
That 0x6B could be a significant problem. 16khz is pretty slow.
As stated above, timing errors may or may not be a problem.
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Washington
Offline Offline
God Member
*****
Karma: 38
Posts: 790
Firefox & Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I uploaded a new version with support for 4MHz, 4.8Mhz and better support for 9.6MHz.
Logged

Avoid throwing electronics out as you or someone else might need them for parts or use.
Solid state rectifiers are the only REAL rectifiers.
Resistors for LEDS!

Pages: 1 [2] 3 4 ... 16   Go Up
Jump to: