Show Posts
Pages: 1 2 3 [4] 5 6 ... 14
46  Forum 2005-2010 (read only) / Syntax & Programs / Re: Rainbow calculator on: April 23, 2007, 12:48:37 pm
I can't resist a project that makes pretty colors. I wired up an 3 potentiometer, 3 LED light and programmed it for HSV controls from the pots. I have two suggestions for improvement, one coding and one visual.

In your code you repeat a number of calculations in the switch statement with enough differences that they don't get optimized into one evaluation, I implemented them once to keep the code size down.

More importantly... Human eyes are not linear. As a very rough estimate, if you were to divide brightness up from 1 to 7, you have to double the number of photons with each step to make them look uniform. If you just run 'value' into the analog to digital converters you get a 'value' knob that is very sensitive  at the low end and nearly flat at the high end.

This code addresses both of those issues. It still isn't great, the 'value' and 'saturation' knobs feel about right, but the 'hue' knob  does not feel smooth. I must study color perception more deeply. It also ignores differences in brightness of the red, green, and blue LEDs, but that is ok if you handle it in the current limiting resistor.
Code:
#include <avr/pgmspace.h>

// This is is an exponential function, scaled and shifted so 0..255 maps onto 0..255
// For i from 0 to 255... round( pow( 2.0, i/32.0) - 1)
// We are going to use it to compensate for the nonlinearity of human vision.
// The PROGMEM keeps it in flash instead of SRAM, but we must use
// special functions to access it.
static const PROGMEM uint8_t delog[] = {
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  0,   0,   0,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
  1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
  2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   3,
  3,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,
  5,   5,   5,   5,   5,   5,   5,   6,   6,   6,   6,   6,   6,   6,   7,   7,
  7,   7,   7,   8,   8,   8,   8,   8,   9,   9,   9,   9,   9,  10,  10,  10,
  10,  11,  11,  11,  11,  12,  12,  12,  12,  13,  13,  13,  14,  14,  14,  15,
  15,  15,  16,  16,  16,  17,  17,  18,  18,  18,  19,  19,  20,  20,  21,  21,
  22,  22,  23,  23,  24,  24,  25,  25,  26,  26,  27,  28,  28,  29,  30,  30,
  31,  32,  32,  33,  34,  35,  35,  36,  37,  38,  39,  40,  40,  41,  42,  43,
  44,  45,  46,  47,  48,  49,  51,  52,  53,  54,  55,  56,  58,  59,  60,  62,
  63,  64,  66,  67,  69,  70,  72,  73,  75,  77,  78,  80,  82,  84,  86,  88,
  90,  91,  94,  96,  98, 100, 102, 104, 107, 109, 111, 114, 116, 119, 122, 124,
  127, 130, 133, 136, 139, 142, 145, 148, 151, 155, 158, 161, 165, 169, 172, 176,
  180, 184, 188, 192, 196, 201, 205, 210, 214, 219, 224, 229, 234, 239, 244, 250,

};

void getRGB(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b)
{
  // I feel I should explain fixed point arithmetic in more detail, but this is
  // is not the place.
  uint8_t sector = h/60U;
  uint8_t remainder = (h - sector*60U) * 64U / 15U;  // 64/15 is really 256/60, but lets stay clear of overflows
  uint8_t p = v * (255U-s) / 255U;  // s and v are (0.0..1.0) --> (0..255), p is (0..255^2)
  uint8_t q = v * (255UL*255UL-((long)s)*remainder) / (255UL*255UL);  // look, fixed point arithmetic in varying encodings
  uint8_t t = v * (255UL*255UL-((long)s)*(255U -remainder)) / (255UL*255UL);

  switch( sector ) {
  case 0:
    *r = v;
    *g = t;
    *b = p;
    break;
  case 1:
    *r = q;
    *g = v;
    *b = p;
    break;
  case 2:
    *r = p;
    *g = v;
    *b = t;
    break;
  case 3:
    *r = p;
    *g = q;
    *b = v;
    break;
  case 4:
    *r = t;
    *g = p;
    *b = v;
    break;
  default:            // case 5:
    *r = v;
    *g = p;
    *b = q;
    break;
  }
}

void setup()
{
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
}

void loop()  
{
  uint8_t r,g,b;
  int hue,sat,val;
  
  int ana_0 = analogRead(0); // # between 0-1023
  int ana_1 = analogRead(1); // # between 0-1023
  int ana_2 = analogRead(2);
    
  hue=(360*(long)ana_0)>>10; //0-360; //shift bits = /1023
  sat=ana_1>>2;                          //0-255;    
  val=ana_2>>2;                               //0-255;
  
  getRGB(hue,sat,val, &r, &g, &b);
        
  // pgm_read_byte(x+k) is very similar to x[k] for arrays of bytes that are
  // stored in flash with the PROGMEM attribute
  analogWrite(9,pgm_read_byte( delog + r));
  analogWrite(10,pgm_read_byte( delog + g));
  analogWrite(11,pgm_read_byte( delog + b));

  delay(20);
}

47  Forum 2005-2010 (read only) / Syntax & Programs / Re: Rainbow calculator on: March 23, 2007, 02:13:17 pm
I suspect that code can be done with dot products, but if you aren't in a matrix math mood you could use a lookup table with the first quarter cycle of the sine function. That serves both sine and cosine by flopping it about different directions.

Here is one with 256 entries scaled for a byte. Don't sweat the flat spot at the end, it belongs there.

Code:
 0,   1,   3,   4,   6,   7,   9,  10,  12,  14,  15,  17,  18,  20,  21,  23,
 25,  26,  28,  29,  31,  32,  34,  36,  37,  39,  40,  42,  43,  45,  46,  48,
 49,  51,  53,  54,  56,  57,  59,  60,  62,  63,  65,  66,  68,  69,  71,  72,
 74,  75,  77,  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  93,  95,  96,
 97,  99, 100, 102, 103, 105, 106, 108, 109, 110, 112, 113, 115, 116, 117, 119,
120, 122, 123, 124, 126, 127, 128, 130, 131, 132, 134, 135, 136, 138, 139, 140,
142, 143, 144, 146, 147, 148, 149, 151, 152, 153, 155, 156, 157, 158, 159, 161,
162, 163, 164, 166, 167, 168, 169, 170, 171, 173, 174, 175, 176, 177, 178, 179,
181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 211,
212, 213, 214, 215, 216, 217, 217, 218, 219, 220, 221, 221, 222, 223, 224, 225,
225, 226, 227, 227, 228, 229, 230, 230, 231, 232, 232, 233, 234, 234, 235, 235,
236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243, 244, 244,
244, 245, 245, 246, 246, 247, 247, 247, 248, 248, 249, 249, 249, 250, 250, 250,
251, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254, 254, 254, 254,
254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
48  Forum 2005-2010 (read only) / Syntax & Programs / Re: Breadboard Arduino using ATMega8L on: April 14, 2007, 09:11:44 am
I have changed clock rates. There are three issues.
1) You need to change F_CPU in preferences.txt
2) If you are using the serial bootloader, you need to make a new one with your new clock rate. This will require you to use bootcloner from another Arduino or an ICSP device to set your bootloader.
3) In 0007 some timing calls will still be wrong, like delayMicroseconds and SoftwareSerial.
49  Forum 2005-2010 (read only) / Syntax & Programs / Re: print -- String instruction ??? on: April 14, 2007, 07:42:32 pm
About radio modules... depending what sort you have, they babble when there is no transmission.  With that in mind you need to encode your data in some way that transmits a bunch of transitions before your data and then some sort of mark to let you know when your data starts.

There are many fancy and complicated ways of encoding bits onto radio signals that have nice properties like balancing the 0 and 1 time which is important for some radios, or minimizing the transmission time within the constraints of the radio switching, but I think you will get by with a UART and a wake up sequence.

Maybe something like sending "UUUUw" before your data to wake up the receiver and let it adjust its gain. Some of the 'U's will be corrupted or missed, but by the time you see "UUw" you should be fairly sure that data follows. Those 'U' characters are 0x55 which is a lot of 0-1 bit pairs and the "?" is a solid block of 5 ones. It seems an unlikely sequence to get out of the babbling receiver and a good one for the receiver to adjust its gain. Obviously if you are controlling a death ray you might want to use a checksum on the data too.

Keep your bit rate under the bit rate of the radios. This is probably either 2400bps or 4800bps.

Try to use the hardware UARTs. The SoftwareSerial in 0007 has unreliable timing and using the read side of software serial requires your code to be waiting in the read routine when the data arrives.
50  Forum 2005-2010 (read only) / Syntax & Programs / Re: Logical boolean operators on: April 10, 2007, 10:10:38 am
You are going to need OR operators for that.
Alternatively, you might like to read this better, notice the "not" operator out front and the "finish condition" inside, so it is a "while not finished" loop.
Code:
while( ! (targetR == R && targetG == G && targetB == B))
Oh look, you have a typo near the end, you have "targetG != B", that isn't going to be good either.
51  Forum 2005-2010 (read only) / Syntax & Programs / Re: writing to flash memory on: March 30, 2007, 01:28:42 pm
Your pagenumber will be the address of the variable divided by SPM_PAGESIZE.
If you have a second Arduino you can use the bootcloner sketch to reflash your first arduino in the event of an embarassing miscalculation that overwrites your bootloader.

It would be safer to use the EEPROM. http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html I don't think anything in the base Arduino uses the EEPROM so you could use all 512 bytes however you see fit.  One trick, I think if I read the bootloader correctly the EEPROM is erased when you upload a sketch. Or maybe not, but be aware that it could happen.
52  Forum 2005-2010 (read only) / Syntax & Programs / Re: writing to flash memory on: March 30, 2007, 12:39:04 pm
[[ discussion of how to proceed deleted in favor of the following ]]

The AVR library has support for writing flash pages.
http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html

The usage example pretty well covers it. Be aware that you have to write full pages which are 64 bytes on a mega8 and 128 on a mega168 (Use the SPM_PAGESIZE macro). And page number will be the address divided by SPM_PAGESIZE.

Another handy piece for this puzzle is to force your variables to be aligned on a page boundary so you don't have to mess around with it too much.

Code:
uint8_t myCollectedData[512] __attribute__ ((aligned (64)));
53  Forum 2005-2010 (read only) / Syntax & Programs / Re: writing to flash memory on: March 30, 2007, 11:26:07 am
Making your static data stay in flash is easy. You just use the PROGMEM modifier from <avr/pgmspace.h> and for string constants wrap them in a PSTR(). The trick is that you can't reference it directly anymore, you have to use the access functions from that header like pgm_read_byte().
54  Forum 2005-2010 (read only) / Syntax & Programs / Re: Serial Printing problems on: March 25, 2007, 03:32:59 pm
I think what your code is doing is counting how many times through the loop that the heart pin was high. This will undoubtedly overflow your variable and look like a random number. You probably mean to count how many times it switches from 0 to 1.

You might also wish to initialize time to timer0_overflow_count+20000. It doesn't have to start at zero, it will be ticking away during program initialization.
55  Forum 2005-2010 (read only) / Syntax & Programs / Re: Arduino Clock on: March 23, 2007, 02:03:55 pm
You can check the millis() call after each heartbeat until you get around 20 seconds from your start time.
56  Forum 2005-2010 (read only) / Syntax & Programs / Re: compare chars? on: March 18, 2007, 11:33:39 pm
C strings have an implicit NUL character at the end. That is a character with the integer value of 0. You could make that array be 11 characters long and it would work.
57  Forum 2005-2010 (read only) / Syntax & Programs / Re: compare chars? on: March 18, 2007, 03:46:23 pm
You probably want to use a function called memcmp().

It will compare a section of memory, like your 10 characters, and tell you if they are lesser, greater, or equal by returning <0, >0, or 0.

Code:
#include <string.h>

/* that include gets you: int memcmp(const void *b1, const void *b2, size_t len); */
/* it may already be included, it was in the sketch I just tested with. */

void loop()
{
  char a[10], b[10];

  // stuff happens

  if ( memcmp(a,b,10) == 0) {
    // more stuff happens
  }
}


58  Forum 2005-2010 (read only) / Interfacing / Re: Graphic LCD 128x64 STN LED Backlight on: April 10, 2007, 10:49:05 am
I wonder if the guy that wrote that datasheet felt bad about lying on his resume?

Without getting fancy you are going to need a lot of pins.
You will want 8 pins for the DB0-7 lines, 2 for CS1 and CS2, and one each for E, RS, and R/W.
The backlight power supply voltage concerns me. 4.2V.  Put a diode between the 5v line and the backlight to drop the voltage a bit and hopefully be in spec.

The read and write cycle timings are fairly straightforward, I think this little pseudo code would keep you in spec...
Code:
Initialize E high and keep it there unless in a read or write.

Write Cycle:
  Set R/W low
  Set CS1 or 2 depending which IC you are writing
  Set RS and DB0-7 according to the function table
  Set E low
  Set E high
  Set E low
  Turn off Both CS1 and CS2
  Set E high

Read Cycle:
  Set R/W high
  Set CS1 or 2 depending which IC you are reading
  Set RS according to the function table
  Set E low
  Set E high
  Read the data pins
  Set E low
  Turn off Both CS1 and CS2
  Set E high

Once you have code for those two functions then you can look at the Display Control Instruction table and start trying some of the simple ones.

The sparkfun forums have a number of threads on using this module. http://forum.sparkfun.com/viewtopic.php?t=4772 is a good start. Especially note the section about a negative voltage for adjusting contrast.
59  Forum 2005-2010 (read only) / Interfacing / Re: Arduino and 1-wire on: January 16, 2007, 09:47:41 pm
All packaged in C++ form. Well, not the keywords.txt file. I'm not sure what that is, though I guess it has something to do with the color coding of the build in editor.

http://www.federated.com/~jim/onewire/ contains the library and a sample program. Feel free to vacuum it up into anything you like.

This library is general 1-wire. It might be nice to derive a DS18S20 class from this that knows about temperature to handle the conversions, or that might start making too much object code. Maybe I'm being too sensitive to code bloat, but it seems that higher level libraries will end up containing a lot of unused functions for any given application. e.g. I won't use the alarm threshold registers in my application but I'd end up with functions for them linked into my code. I had enough worry about that in just the generic functions that I ended up with a couple nasty preprocessor symbols to omit some of the larger functions that people might not need.
60  Forum 2005-2010 (read only) / Interfacing / Re: Arduino and 1-wire on: January 14, 2007, 05:01:40 pm
Oh OK. After I got done putting in all the rubbish to make the C++ and C symbols work together I did feel it would be better as a class. I'm away from that hardware until Tuesday, I'll redo it as C++ then.
Pages: 1 2 3 [4] 5 6 ... 14