Show Posts
Pages: [1] 2
1  Using Arduino / Project Guidance / Re: idea for a way to store data in flash from running program on: December 23, 2012, 06:12:05 pm
I agree, that using extra parts would be way simpler to implement. I was just curious about if it could be done. I'll try to understand what this pile of hieroglyphics aka the bootloader code actually means. Maybe if I stare at it for a few months or years, I can figure out what I'm doing and give it a try. Or if anybody with some actual knowledge wants to give it a shot...
2  Using Arduino / Project Guidance / idea for a way to store data in flash from running program on: December 23, 2012, 05:15:20 pm
Can somebody tell me if this would be possible or not (and why)? Seems like it could be very useful.

Bootloader looks into eeprom during startup
it adds the data from eeprom into a location in flash (maybe have the first part of the eeprom data be instructions for where to store it)
run program
 program does it's thing. now you can also read the data that is saved into flash
 at some point, I want to store more data. so, write more data to the eeprom and trigger a reset
process repeats...

This way if you needed more non-volatile storage than the amount of eeprom you have (like you want to record 5k of data), you could use your extra flash space instead. I know it would be slow, but in some cases that doesn't really matter. I'm mostly interested in if this would be possible or not. I mentioned this in another thread I had asked a question in, but it seemed like an idea that should have its own topic to me.
3  Using Arduino / Project Guidance / Re: storing ir remote codes in non-volatile memory on: December 23, 2012, 03:16:42 pm
Thanks for the clarification. I would like to make this device not be computer dependent, so I guess program memory is out.
4  Using Arduino / Project Guidance / Re: storing ir remote codes in non-volatile memory on: December 23, 2012, 02:50:15 pm
Just a thought... Would it be possible to have the bootloader copy data in eeprom into flash on reset? So it would go something like this...

reset
bootloader copies value of eeprom into an area of flash after existing program and deletes eeprom
during program, save something new into eeprom
repeat

Although I'm not sure how you could delete old info you don't want anymore that is now in flash. Does this seem doable? Has anybody already done something like this?
5  Using Arduino / Project Guidance / Re: storing ir remote codes in non-volatile memory on: December 23, 2012, 02:29:20 pm
It's really not that hard even with IDE 0022 and has been streamlined a bit since. I can give you cookbook for 0022 and it will probably work but you might want the newer syntax.
Am I correct in interpreting this as you saying there IS a way to save to program memory while the program is running? I can't seem to find anybody else who says this is possible.
6  Using Arduino / Project Guidance / Re: storing ir remote codes in non-volatile memory on: December 23, 2012, 12:20:11 pm
Those are good suggestions. I had never even heard of F-ram before. Looks very good for some applications (speedy and large storage sizes available), but the chips seem fairly expensive compared to the other options.
Quote
It's really not that hard even with IDE 0022 and has been streamlined a bit since..
Can you point me to some more info on how to do this? I think this is my preferred option. Otherwise, I think I'll just have to get some eeprom chips and play with those. Also, for the people that know about eeprom, is there anything I should look for, or avoid specifically in a chip? For example I've seen serial and parallel versions, and I probably don't want to waste more pins than I need to with a parallel chip.
7  Using Arduino / Project Guidance / Re: storing ir remote codes in non-volatile memory on: December 23, 2012, 02:48:16 am
Yes, I've looked at that. The thing I wanted to do differently was to be able to save codes and play them back without having to know the protocol. His code has the raw mode if it can't id the protocol, which is similar to what I'm doing, but he is using 50uS resolution for recording codes. I'd need to mess around with more devices to see if that is always enough precision. Also I'm not understanding where he is saving the codes, or in what form. Could somebody explain that? On reading through his code again, it makes me wonder if I really need to store times that are so big. The longest signal pulse I've seen in the start or middle of a code is about 10ms. Anything longer is always at the end, and it's when the carrier is turned off. I suppose I could just always leave a big-ish delay after sending any code and not worry about storing the longer times. Using 50uS resolution and up to just 12mS times in the code can get the times down to 8 bits each, or up to 15 codes in eeprom. I don't think 15 codes would be enough, though. I can't think of a way to shrink the codes more than that without just giving up more resolution? Any ideas? I'm really thinking I'll need external storage of some kind. Any suggestions on that?
8  Using Arduino / Project Guidance / Re: storing ir remote codes in non-volatile memory on: December 23, 2012, 01:21:50 am
Thanks for the reply. I was thinking that if the bootloader can write to flash, then so could I. However, after some more reading, it seems like it is not something I want to try to tackle. It looks like I will need to find a way to shrink the info I'm storing, or have some kind of extra storage. Any recommendations on what I could use to store the codes? It doesn't need to be particularly fast, as I can read it into memory before sending. Or how I could shrink the codes to fit a reasonable number into eeprom? If I give up some resolution on the times, I can scale them down before storing and then scale them up again after reading back and before transmitting. The biggest delay I've seen in a code is at the end, before the code repeats. It was about 40mS. So I think about 60,000uS is the longest thing I would need to store to be safe. The variation I've seen in times for a remote code pulse is about 25uS. If I divide my times which currently have 1uS resolution by 15 to get 15uS resolution, I think that would still be close enough to work. So doing that, I could get away with storing my times as 12 bit numbers [15 * (2^12 - 1) = 61425] instead of 32 bit numbers. Anyone know how to store 12 bit numbers in an array? Or do i have to combine them somehow and disassemble them again later to store in another data type? But that would still take up 12 * 68 / 8 = 102 bytes per code, so I could only save 10 codes. Any ideas how to shrink it more, without having to know the protocol being used? Or recommendations for some kind of external storage to use?
9  Using Arduino / Project Guidance / storing ir remote codes in non-volatile memory on: December 22, 2012, 10:46:10 pm
I'm working on making a universal remote control for ir devices around my house. So far I have an arduino device (atmega328p @ 8MHz) and sketch that allow me to monitor an ir receiver and record the on and off times for the signal being received. It then replays the same signal with an ir led. The circuit is an ir led connected to pin 11 and an ir receiver hooked up to pin 2. Here is the script I have now.
Code:
#include <avr/io.h>

const unsigned long F_IR = 38000; // IR frequency, in hz
const unsigned int PRESCALE = 1; // match this with the values in TCCR2B CS22, CS21, CS20
const byte Timer2APin = 11; // OC2A PIN = PORT B PIN 3 = ATMEGA328 PIN 17 = ARDUINO PIN 11
volatile unsigned int IRPulseNum = 0; // make a counter for IR pulse length array
const byte codeLength = 68; // one each for hi and low part of each bit
// enough to record a start bit, 32 code bits,and a stop bit
// still need to find out if this is long enough for all ir codes...
volatile unsigned int code[codeLength]; // make array to hold IR pulse lengths
volatile unsigned long pulseStart; // this will be used to measure pulses from receiver

void setup(){
  pinMode(2, INPUT); // set interrupt pin as input
  digitalWrite(2, HIGH); // turn on the pullup. is this needed?
  pinMode(Timer2APin, INPUT); // SETS DATA DIRECTION REGISTER
  // OUTPUT WILL NOT SHOW UP WHILE SET TO INPUT
  // OUTPUT WILL SHOW UP WHILE SET TO OUTPUT

    // SET VALUE OF TCCR2A
  // (0 << COM2A1) | (1 << COM2A0)             TOGGLE OC2A PIN ON COMPARE MATCH
  // (0 << COM2B1) | (0 << COM2B0)             OC2B PIN DISCONNECTED
  // (1 << WGM21) | (0 << WGM20)               CTC MODE - WGM22 IN TCCR2B MUST ALSO BE 0
  TCCR2A = ((0 << COM2A1) | (1 << COM2A0) | (0 << COM2B1) | (0 << COM2B0) | (1 << WGM21) | (0 << WGM20));
  // SET VALUE OF TCCR2B
  // (0 << FOC2A) | (0 << FOC2B)               FORCE OUT COMPARE A AND B OFF
  // (0 << WGM22)                              CTC MODE - WGM21 AND WGM20 IN TCCR2A MUST ALSO BE 1 AND 0 RESPECTIVELY
  // (0 << CS22) | (0 << CS21) | (1 << CS20)   CLOCK SELECT - NO PRESCALAR
  TCCR2B = ((0 << FOC2A) | (0 << FOC2B) | (0 << WGM22) | (0 << CS22) | (0 << CS21) | (1 << CS20));

  TCNT2 = 0; // RESET COUNTER2 VALUE
  OCR2A = F_CPU / F_IR / 2 / PRESCALE - 1; // SET TOP COUNTER2 VALUE (FOR CTC)
  // have to set this value AFTER the counter starts or it won't work!
  // F_CPU is already defined in the board.txt file
  // just a rearranged formula from datasheet for ctc
  //                f_clk_io
  // f_OC2A = ---------------------------
  //           2 * prescale * (1 + OCR2A)

  attachInterrupt(0, IRDetectLow, FALLING); // put interrupt on pin 2 to detect ir code start
}

void loop(){
  if (IRPulseNum == codeLength){ // this only happens when the code is done recording
    Serial.begin(9600); // turn on serial
    delay(1000); // wait a little to give serial time to start up and not miss anything
    // print out the array of carrier on and off times that was recorded
    Serial.println("Code:");
    for (byte i = 0; i < codeLength; i++)
    {
      if (i % 2 == 0){
        Serial.print("Code[");
        Serial.print(i);
        Serial.print("]: Signal on for ");
      }
      else{
        Serial.print("Code[");
        Serial.print(i);
        Serial.print("]: No signal for ");
      }
      Serial.print(code[i]);
      Serial.println(" microseconds");
    }
    Serial.end(); // don't need this anymore
    IRPulseNum++; // this will trigger the next if statement
  }
  if (IRPulseNum > codeLength){ // only happens once code is recorded and sent back to computer
    delay(15000); // wait a while
    for (byte i = 0; i < codeLength; i++){ // loop though the recorded array turning the ir signal
      // on and off for the recorded times
      if(i % 2 == 0){ // even array indexes (carrier on)
        pinMode(Timer2APin, OUTPUT); // turn ir signal on
      }
      else{ // odd array indexes (carrier off)
        pinMode(Timer2APin, INPUT); // turn ir signal off
      }
      delayMicroseconds(code[i]); // wait for the amount of time from the array
    }
    pinMode(Timer2APin, INPUT); // turn ir signal off once whole code is sent
  }
}

void IRDetectLow(){ // this runs when carrier start is detected
  if (IRPulseNum == codeLength - 1){ // if last spot in array
    code[IRPulseNum]= micros() - pulseStart; // calculate how long carrier was off
    IRPulseNum++; // increment array counter. used to signal recording is over
    detachInterrupt(0); // turn off interrupt because recording is done
  }
  else{ // not the last spot in array
    if (IRPulseNum > 0){ // if it's not the first pulse
      code[IRPulseNum]= micros() - pulseStart; // calculate how long carrier was off
      IRPulseNum++; // increment array counter
    }
    attachInterrupt(0, IRDetectHigh, RISING); // switch the interrupt to watch for carrier end
    pulseStart = micros(); // record the time when carrier start was detected
  }
}

void IRDetectHigh(){ // this runs when carrier end is detected
  if (IRPulseNum == codeLength - 1){ // if last spot in array
    code[IRPulseNum]= micros() - pulseStart; // calculate how long carrier was on
    IRPulseNum++; // increment array counter. used to signal recording is over
    detachInterrupt(0); // turn off interrupt because recording is done
  }
  else{ // not the last spot in array
    code[IRPulseNum]= micros() - pulseStart; // calculate how long carrier was on
    IRPulseNum++; // increment array counter
    attachInterrupt(0, IRDetectLow, FALLING); // switch the interrupt to watch for carrier start
    pulseStart = micros(); // record the time when carrier end was detected
  }
}
Eventually, I want to be able to save the code and assign it to a button that will play it back. The way it's saved in the array now takes up quite a bit of space (68 unsigned longs * 4 bytes ea = 272 bytes for one code). I realize there are other ways of saving these codes, but this is the most universal way I can think of. I think it should be basically protocol independent as long as you record a long enough signal. Now I'm trying to figure out the best way to save this data. I want it to keep the settings when it turns off, and I would like to save at least a couple dozen codes. Is saving the data into program memory a good option here? If the program took up no space I'd have room for about 117 codes. I'm not sure how big the rest of the program will be when it's doing everything I want it to. What options do I have here? It looks like eeprom chips are pretty cheap, but I've never used one before. Are they a good option here? Are they simple to use? Is there some other option I'm overlooking? Suggestions, comments, or criticisms welcome.
10  Using Arduino / Programming Questions / Re: Generating 38kHz pulse for ir project on: December 21, 2012, 09:30:15 pm
So just to make sure I understand what I'm reading / doing here, the #define part is there for the compiler, right? An you would do that instead of making a variable because you don't actually need the arduino to know what the number is, so you save some space by having the compiler replace it before uploading?
11  Using Arduino / Programming Questions / Re: Generating 38kHz pulse for ir project on: December 21, 2012, 09:20:25 pm
Awesome! Thanks! I figured it was something sneaky like that.
12  Using Arduino / Programming Questions / Re: Generating 38kHz pulse for ir project on: December 21, 2012, 08:09:28 pm
Also, using a camera, I can see that the ir led is lighting up at least somewhat for 5 seconds and then off for 5 seconds.
13  Using Arduino / Programming Questions / Re: Generating 38kHz pulse for ir project on: December 21, 2012, 08:08:01 pm
After putting the bootloader on it, I uploaded the blink example to make sure the clock was working right and it was running at the right speed. The blinking speed was right, and everything seemed ok. Is that what you meant?
14  Using Arduino / Programming Questions / Re: Generating 38kHz pulse for ir project on: December 21, 2012, 07:53:55 pm
Also, I know people have libraries to do this already, but I want to understand what I'm doing. I think I'll learn more and understand better by writing my own code and asking questions.
15  Using Arduino / Programming Questions / Generating 38kHz pulse for ir project on: December 21, 2012, 07:52:05 pm
I'm trying to work my way step by step through building a remote control for the tv in my dining room. This is the part I'm on now. I have a 328p that I put a bootloader on using this board file:
Code:
##############################################################
atmega328p8int2_7v.name=Atmega328P 8MHz internal 2.7v
atmega328p8int2_7v.upload.protocol=arduino
atmega328p8int2_7v.upload.maximum_size=30720
atmega328p8int2_7v.upload.speed=9600
atmega328p8int2_7v.bootloader.low_fuses=0xe2
atmega328p8int2_7v.bootloader.high_fuses=0xd8
atmega328p8int2_7v.bootloader.extended_fuses=0x05
atmega328p8int2_7v.bootloader.path=optiboot
atmega328p8int2_7v.bootloader.file=optiboot_atmega328.hex
atmega328p8int2_7v.bootloader.unlock_bits=0x3F
atmega328p8int2_7v.bootloader.lock_bits=0x0F
atmega328p8int2_7v.build.mcu=atmega328p
atmega328p8int2_7v.build.f_cpu=8000000L
atmega328p8int2_7v.build.core=arduino
atmega328p8int2_7v.build.variant=standard
So, my first question is about these fuse settings. They seem to be working, but is there anything weird about them that could cause trouble?

Next topic... Here is my program's code so far (comments explain what I think it should be doing):
Code:
#include <avr/io.h>

int Timer2APin = 11; // OC2A PIN = PORT B PIN 3 = ATMEGA328 PIN 17 = ARDUINO PIN 11

void setup(){
  pinMode(Timer2APin, INPUT); // SETS DATA DIRECTION REGISTER
  // OUTPUT WILL NOT SHOW UP WHILE SET TO INPUT
  // OUTPUT WILL SHOW UP WHILE SET TO OUTPUT

  TCNT2 = 0; // RESET COUNTER2 VALUE
  OCR2A = 104; // SET TOP COUNTER2 VALUE (FOR CTC)
  // formula from datasheet for ctc
  //                f_clk_io
  // f_OC2A = ---------------------------
  //           2 * prescale * (1 + OCR2A)
 
  //               8000000
  // f_OC2A = ------------------- = 38095.2381 Hz
  //           2 * 1 * (1 + 104)

  // SET VALUE OF TCCR2A
  // (0 << COM2A1) | (1 << COM2A0)             TOGGLE OC2A PIN ON COMPARE MATCH
  // (0 << COM2B1) | (0 << COM2B0)             OC2B PIN DISCONNECTED
  // (1 << WGM21) | (0 << WGM20)               CTC MODE - WGM22 IN TCCR2B MUST ALSO BE 0
  TCCR2A = ((0 << COM2A1) | (1 << COM2A0) | (0 << COM2B1) | (0 << COM2B0) | (1 << WGM21) | (0 << WGM20));
  // SET VALUE OF TCCR2B
  // (0 << FOC2A) | (0 << FOC2B)               FORCE OUT COMPARE A AND B OFF
  // (0 << WGM22)                              CTC MODE - WGM21 AND WGM20 IN TCCR2A MUST ALSO BE 1 AND 0 RESPECTIVELY
  // (0 << CS22) | (0 << CS21) | (1 << CS20)   CLOCK SELECT - NO PRESCALAR
  TCCR2B = ((0 << FOC2A) | (0 << FOC2B) | (0 << WGM22) | (0 << CS22) | (0 << CS21) | (1 << CS20));
}

void loop(){
  pinMode(Timer2APin, OUTPUT); //let the timer pin toggle for 5 seconds
  delay(5000);
  pinMode(Timer2APin, INPUT); //stop it for 5 seconds
  delay(5000); 
}
So, it would seem that one or more of the things above are not working as expected. Circuit picture is in attachment. This is the receiver I'm using:
http://www.mouser.com/ProductDetail/Vishay-Semiconductors/TSOP38338SS1V/?qs=sGAEpiMZZMsj2w6QBC0lciAHmYLQvta4
I was expecting to see the led hooked up to the detector alternate between on and off for 5 seconds at a time. Instead it is almost always on dimly, and it sort of flickers every once in a while. I hooked up another arduino as a logic analyzer and got what looked like erratically spaced pulses of varying lengths. Any ideas what is wrong with my code?
Pages: [1] 2