Changing library to work with attiny45

I am working with http://sebastian.setz.name/arduino/my-libraries/multi-camera-ir-control/ The problem I am having is that it works perfectly on my uno but as soon as I put it on attiny45 p20 it no longer triggers the camera. I have a theory on why it wont work but even if I am right im not sure how to go about fixing it.

My theory is that I am programming the attiny45 at 8mhz and the clock for the uno is 16mhz. So in the cpp and .h something has to be changed to reflect that. Or maybe I am way off. Hopefully someone will be able to shed some light on this for me. I am attaching everything that may be relevant. ANy help would be greatly appreciated.

sketch

#include <multiCameraIrControl.h>
 
Canon D5(2);
 
void setup(){
}
 
void loop(){
  D5.shutterNow();
  delay(200);
  
}

multiCameraIrControl.h

#ifndef multiCameraIrControl_h
#define multiCameraIrControl_h

#if ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

class Nikon{
public:
  Nikon(int pin);
  void shutterNow();
private:
  int _pin;
  int _freq;
};

class Canon{
public:
  Canon(int pin);
  void shutterNow();
  void shutterDelayed();
private:
  int _pin;
  int _freq;
};

class CanonWLDC100{
public:
  CanonWLDC100(int pin);
  void shutterNow();
private:
  int _pin;
  int _freq;
};
 
class Pentax{
public:
  Pentax(int pin);
  void shutterNow();
  void toggleFocus();
private:
  int _pin;
  int _freq;
};

class Olympus{
public:
  Olympus(int pin);
  void shutterNow();
  void zoomin(unsigned int pct);
  void zoomout(unsigned int pct);
private:
  int _pin;
  int _freq;
};

class Minolta{
public:
  Minolta(int pin);
  void shutterNow();
  void shutterDelayed();
private:
  int _pin;
  int _freq;
};

class Sony{
public:
  Sony(int pin);
  void shutterNow();
  void shutterDelayed();
  void toggleVideo();
private:
  int _pin;
  int _freq;
};

#endif

multiCameraIrControl.cpp

#if ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

#include "multiCameraIrControl.h"

void wait(unsigned int time){
  unsigned long start = micros();
  while(micros()-start<=time){
  }
}

void high(unsigned int time, int freq, int pinLED){
  int pause = (1000/freq/2)-4;
  unsigned long start = micros();
  while(micros()-start<=time){
    digitalWrite(pinLED,HIGH);
    delayMicroseconds(pause);
    digitalWrite(pinLED,LOW);
    delayMicroseconds(pause);
  }
}

Nikon::Nikon(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
  _freq = 40;
}

void Nikon::shutterNow()
{
  high(2000,_freq,_pin);
  wait(27830);
  high(390,_freq,_pin);
  wait(1580);
  high(410,_freq,_pin);
  wait(3580);
  high(400,_freq,_pin);
}

Pentax::Pentax(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
  _freq = 38;
}

void Pentax::shutterNow()
{
  high(13000,_freq,_pin);
  wait(3000);
  for (int i=0;i<7;i++){
    high(1000,_freq,_pin);
    wait(1000);
  };
}

void Pentax::toggleFocus()
{
  high(13000,_freq,_pin);
  wait(3000);
  for (int i=0;i<5;i++){
    high(1000,_freq,_pin);
    wait(1000);
  };
  high(1000,_freq,_pin);
  wait(3000);
  high(1000,_freq,_pin);
}

Olympus::Olympus(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
  _freq = 40;
}

void Olympus::shutterNow()
{
  bool _seq[] = {
    0,1,1,0,0,0,0,1,1,1,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1    };
  high(8972,_freq,_pin);
  wait(4384);
  high(624,_freq,_pin);
  for (int i=0;i<sizeof(_seq);i++){
    if (_seq[i]==0){
      wait(488);
      high(600,_freq,_pin);
    }
    else{
      wait(1600);
      high(600,_freq,_pin);
    }
  };
}

void Olympus::zoomin(unsigned int pct)
{
  bool _seq[] = {
    0,1,1,0,0,0,0,1,1,1,0,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1    };
  high(9000,_freq,_pin);
  wait(4500);
  high(500,_freq,_pin);
  for (int i=0;i<sizeof(_seq);i++){
    if (_seq[i]==0){
      wait(500);
      high(500,_freq,_pin);
    }
    else{
      wait(1500);
      high(500,_freq,_pin);
    }
  };
  wait(40000);
  if (pct>100) pct = 100;
  pct = (pct*52)/100 + 1;
  for (int i=1; i<pct; i++)
  {
    high(9000,_freq,_pin);
    wait(2000);
    high(500,_freq,_pin);
    wait(96000);
  }

}

void Olympus::zoomout(unsigned int pct)
{
  bool _seq[] = 
             {0,1,1,0,0,0,0,1,1,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,1 };
  high(9000,_freq,_pin);           // 
  wait(4500);
  high(500,_freq,_pin);
  for (int i=0;i<sizeof(_seq);i++){
    if (_seq[i]==0){
      wait(500);
      high(500,_freq,_pin);
    }
    else{
      wait(1500);
      high(500,_freq,_pin);
    }
  };
  wait(40000);
  if (pct>100) pct = 100;
  pct = (pct*70)/100 + 1;
  for (int i=1; i<pct; i++)
  {
    high(9000,_freq,_pin);
    wait(2000);
    high(500,_freq,_pin);
    wait(96000);
  }
}

Minolta::Minolta(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
  _freq = 38;
}

void Minolta::shutterNow()
{
  bool _seq[] = {
    0,0,1,0,1,1,0,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1    };
  high(3750,_freq,_pin);
  wait(1890);
  for (int i=0;i<sizeof(_seq);i++){
    if (_seq[i]==0){
      high(456,_freq,_pin);
      wait(487);
    }
    else{
      high(456,_freq,_pin);
      wait(1430);
    }
  };
}

void Minolta::shutterDelayed()
{
  bool _seqDelayed[] = {
    0,0,1,0,1,1,0,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1    };
  high(3750,_freq,_pin);
  wait(1890);
  for (int i=0;i<sizeof(_seqDelayed);i++){
    if (_seqDelayed[i]==0){
      high(456,_freq,_pin);
      wait(487);
    }
    else{
      high(456,_freq,_pin);
      wait(1430);
    }
  };
}

Sony::Sony(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
  _freq = 40;
}

void Sony::shutterNow()
{
  bool _seq[] = {
    1,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,1,1,1,1    };
  for (int j=0;j<3;j++) {
    high(2320,_freq,_pin);
    wait(650);
    for (int i=0;i<sizeof(_seq);i++){
      if (_seq[i]==0){
        high(575,_freq,_pin);
        wait(650);
      }
      else{
        high(1175,_freq,_pin);
        wait(650);
      }
    }
    wait(10000);
  }
}

void Sony::shutterDelayed()
{
  bool _seqDelayed[] = {
    1,1,1,0,1,1,0,0,1,0,1,1,1,0,0,0,1,1,1,1    };
  for (int j=0;j<3;j++) {
    high(2320,_freq,_pin);
    wait(650);
    for (int i=0;i<sizeof(_seqDelayed);i++){
      if (_seqDelayed[i]==0){
        high(575,_freq,_pin);
        wait(650);
      }
      else{
        high(1175,_freq,_pin);
        wait(650);
      }
    }
    wait(10000);
  }
}

void Sony::toggleVideo()
{
  bool _seqToggle[] = {
    0,0,0,1,0,0,1,0,1,0,1,1,1,0,0,0,1,1,1,1    };
  for (int j=0;j<3;j++) {
    high(2320,_freq,_pin);
    wait(650);
    for (int i=0;i<sizeof(_seqToggle);i++){
      if (_seqToggle[i]==0){
        high(575,_freq,_pin);
        wait(650);
      }
      else{
        high(1175,_freq,_pin);
        wait(650);
      }
    }
    wait(10000);
  }
}

Canon::Canon(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
  _freq = 33;
}

void Canon::shutterNow()
{
 for(int i=0; i<16; i++) { 
    digitalWrite(_pin, HIGH);
    delayMicroseconds(11);
    digitalWrite(_pin, LOW);
    delayMicroseconds(11);
  } 
  delayMicroseconds(7330); 
  for(int i=0; i<16; i++) { 
    digitalWrite(_pin, HIGH);
    delayMicroseconds(11);
    digitalWrite(_pin, LOW);
    delayMicroseconds(11);
  }
}

void Canon::shutterDelayed()
{
  for(int i=0; i<16; i++) { 
    digitalWrite(_pin, HIGH);
    delayMicroseconds(11);
    digitalWrite(_pin, LOW);
    delayMicroseconds(11);
  } 
  delayMicroseconds(5360); 
  for(int i=0; i<16; i++) { 
    digitalWrite(_pin, HIGH);
    delayMicroseconds(11);
    digitalWrite(_pin, LOW);
    delayMicroseconds(11);
  }
}

CanonWLDC100::CanonWLDC100(int pin)
{
  pinMode(pin, OUTPUT);
  _pin = pin;
  _freq = 38;
}
 
void CanonWLDC100::shutterNow()
{
  bool _seq[] = {0,1,0,1,0,0,1,1,1,0,0,0,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1};
  high(9042,_freq,_pin);
  wait(4379);
 
  for (int i=0;i<sizeof(_seq);i++){
    if (_seq[i]==0){
      high(612,_freq,_pin);
      wait(512);
    }
    else{
      high(612,_freq,_pin);
      wait(1621);
    }
  };
    high(599,_freq,_pin);
}

I had another thought that might be easier. If I am correct about the clock speed needing to 16mhz would it be possible to simply add a crystal and 2 caps to make it clock like the UNO?

That may not be necessary. The t85 family has a PLL (Phase Locked Loop) that allows it to run at 16 MHz using the internal oscillator. A simple fuse change gets it working. If you are using the Tiny Core... Google Code Archive - Long-term storage for Google Code Project Hosting. ...just select the ATtiny85 @ 16 MHz (internal PLL; 4.3 V BOD) board and execute Tools / Burn Bootloader.

You will very likely have to tune the oscillator. You can use Poor Man's Tiny Tuner or, if you're patient, you can wait until version 2 is ready later this week.

Wow that is great info. I just had a look at the poor mans tiny tuner and it looks a bit complicated. I can wait for the V2 :slight_smile: should i just keep checking Google Code Archive - Long-term storage for Google Code Project Hosting. for the 2.0 version? (which I assume will re-tune the oscillator when I select 16mhz and burn the bootloader automatically?)

OK and another question you said that I should select ATtiny85 @ 16 MHz (internal PLL; 4.3 V BOD) Will that work on the attiny45? Because I don;t see a 45 option for 16Mhz
see screenshot

zerocool5878:
…should i just keep checking http://code.google.com/p/arduino-tiny/ for the 2.0 version?

You should bug me on Friday (personal message or post here). Anything shiny will distract me and then I’ll never get it done.

(which I assume will re-tune the oscillator when I select 16mhz and burn the bootloader automatically?)

Correct.

OK and another question you said that I should select ATtiny85 @ 16 MHz (internal PLL; 4.3 V BOD) Will that work on the attiny45?

It will but you will have to create a board entry for it. The file of interest is boards.txt in the Tiny Core directory. If you get stuck, report back.

OK and another question you said that I should select ATtiny85 @ 16 MHz (internal PLL; 4.3 V BOD) Will that work on the attiny45?

It will but you will have to create a board entry for it. The file of interest is boards.txt in the Tiny Core directory. If you get stuck, report back.

Well I opened the boards.txt and was about to copy and paste most of the info from a combination of the 85 and 45 but the cpu id would be different I think?? I am a bit stuck there

The current entry for the t85...

###########################################################################

attiny85at16p.name=ATtiny85 @ 16 MHz (internal PLL; 4.3 V BOD)

# The following do NOT work...
# attiny85at16p.upload.using=avrispv2
# attiny85at16p.upload.using=Pololu USB AVR Programmer

# The following DO work (pick one)...
attiny85at16p.upload.using=arduino:arduinoisp
# attiny85at16p.upload.protocol=avrispv2
# attiny85at16p.upload.using=pololu

attiny85at16p.upload.maximum_size=8192

# PLL Clock; Start-up time PWRDWN/RESET: 1K CK/14 CK + 4 ms; [CKSEL=0001 SUT=00]
# Brown-out detection level at VCC=4.3 V; [BODLEVEL=100]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]
# Serial program downloading (SPI) enabled; [SPIEN=0]

attiny85at16p.bootloader.low_fuses=0xC1
attiny85at16p.bootloader.high_fuses=0xD4
attiny85at16p.bootloader.extended_fuses=0xFF
attiny85at16p.bootloader.path=empty
attiny85at16p.bootloader.file=empty85at16.hex

attiny85at16p.build.mcu=attiny85
attiny85at16p.build.f_cpu=16000000L
attiny85at16p.build.core=tiny

###########################################################################

After replacing "85" with "45"...

###########################################################################

attiny45at16p.name=ATtiny45 @ 16 MHz (internal PLL; 4.3 V BOD)

# The following do NOT work...
# attiny45at16p.upload.using=avrispv2
# attiny45at16p.upload.using=Pololu USB AVR Programmer

# The following DO work (pick one)...
attiny45at16p.upload.using=arduino:arduinoisp
# attiny45at16p.upload.protocol=avrispv2
# attiny45at16p.upload.using=pololu

attiny45at16p.upload.maximum_size=8192

# PLL Clock; Start-up time PWRDWN/RESET: 1K CK/14 CK + 4 ms; [CKSEL=0001 SUT=00]
# Brown-out detection level at VCC=4.3 V; [BODLEVEL=100]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]
# Serial program downloading (SPI) enabled; [SPIEN=0]

attiny45at16p.bootloader.low_fuses=0xC1
attiny45at16p.bootloader.high_fuses=0xD4
attiny45at16p.bootloader.extended_fuses=0xFF
attiny45at16p.bootloader.path=empty
attiny45at16p.bootloader.file=empty45at16.hex

attiny45at16p.build.mcu=attiny45
attiny45at16p.build.f_cpu=16000000L
attiny45at16p.build.core=tiny

###########################################################################

This line will give you trouble...

attiny45at16p.bootloader.file=empty45at16.hex

The "bootloader" is an empty image so we'll just use the one for the t85 processor...

###########################################################################

attiny45at16p.name=ATtiny45 @ 16 MHz (internal PLL; 4.3 V BOD)

# The following do NOT work...
# attiny45at16p.upload.using=avrispv2
# attiny45at16p.upload.using=Pololu USB AVR Programmer

# The following DO work (pick one)...
attiny45at16p.upload.using=arduino:arduinoisp
# attiny45at16p.upload.protocol=avrispv2
# attiny45at16p.upload.using=pololu

attiny45at16p.upload.maximum_size=8192

# PLL Clock; Start-up time PWRDWN/RESET: 1K CK/14 CK + 4 ms; [CKSEL=0001 SUT=00]
# Brown-out detection level at VCC=4.3 V; [BODLEVEL=100]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]
# Serial program downloading (SPI) enabled; [SPIEN=0]

attiny45at16p.bootloader.low_fuses=0xC1
attiny45at16p.bootloader.high_fuses=0xD4
attiny45at16p.bootloader.extended_fuses=0xFF
attiny45at16p.bootloader.path=empty
attiny45at16p.bootloader.file=empty85at16.hex

attiny45at16p.build.mcu=attiny45
attiny45at16p.build.f_cpu=16000000L
attiny45at16p.build.core=tiny

###########################################################################

Wow that is terrific. I burned the boot loader at 16mhz and the sketch instantly works perfect on the attiny45. I didn't even attempt to re-tune the oscillator. I imagine it may be out but not out far enough to be outside of the frequency tolerences for the ir sensor.

I will still look forward to the V2 update to Tiny Core as it would be nice to be able to know it is nice and synced.

Thank you very much Coding Badly

You are welcome.

zerocool5878:
I will still look forward to the V2 update to Tiny Core as it would be nice to be able to know it is nice and synced.

Tiny Tuner 2. At the rate I'm going I'll be pushing up daises before I finish version 2 of the core.

Tiny Tuner 2 requires a continuous stream of 16 ms high pulses. TinyISP is capable of providing what exactly what the tuner needs...

Are you using ArduinoISP (or TinyISP) to program the ATtiny45?

Well I am using ArduinoISP but Monday my avrisp mkii should arrive. WIll that help? I have a dedicated uno that just has ArduinoISP sketch on it. I always have problems with it. Each time I go to use it without fail there is an issue. If it's not a sk500 error its something else. Sometimes it just a wire not making connection and other times I just need to close arduino and restart and then it starts to work as it should. I got aggravated and ordered the avrisp mkii for that reason alone. I could change that uno to TinyISP if that would help me.

Moderator edit: over-quote removed.

zerocool5878:
Well I am using ArduinoISP but Monday my avrisp mkii should arrive. WIll that help?

It will help programming.

But for using Tiny Tuner 2: is it capable of generating a continuous stream of 16 ms high pulses?

I have no idea if the avrisp mkii is capable for that. I tried searching for that answer with no success. Also I might be getting a little confused I just want to make sure I am understanding all of this.

Tiny Core- The sub menu that has a list of the attinys in different configurations. This I have working fine.

Tiny Tuner - From what I gather this is something that you upload to something other then the attiny like to an uno which is basically a sketch that makes the uno send a stream of 16ms pulses on a certain pin. Then that pin is connected to a pin on the attiny that you want to realign somehow? Sorry lol

TinyISP- I thought that this was an alternative to picking ArduinoISP under Tools>programmer I may have this installed wrong because it shows up under examples instead.

zerocool5878:

[quote author=Coding Badly link=topic=163934.msg1228546#msg1228546 date=1367695047]But for using Tiny Tuner 2: is it capable of generating a continuous stream of 16 ms high pulses?

I have no idea if the avrisp mkii is capable for that. I tried searching for that answer with no success.[/quote]

I don't think it does. We'll assume it doesn't.

Tiny Core- The sub menu that has a list of the attinys in different configurations.

Exactly.

Tiny Tuner - From what I gather this is something that you upload to something other then the attiny...

It is something that gets uploaded to the ATtiny. It's packaged as a library. With the first version there were a few examples. But, I plan on only one example with version 2: output the tuned OSCCAL value. That seems to be how everyone uses it.

So, you would load the example sketch in the Arduino IDE, select the appropriate ATtiny board, upload the sketch to the ATtiny, and allow it to run. After a few seconds you would have access to a well tuned OSCCAL value.

After tuning, you would typically put a line of code like the following in your setup...

OSCCAL = 0x60;

Tiny Tuner (2) determines what value to use (the 0x60).

...like to an uno which is basically a sketch that makes the uno send a stream of 16ms pulses on a certain pin.

TinyISP running on the Uno outputs the "tuning pulses" used by Tiny Tuner to tune the ATtiny processor. TinyISP is not strictly required. A frequency generator should work. Anything that can generate the necessary pulse stream.

TinyISP- I thought that this was an alternative to picking ArduinoISP under Tools>programmer.

It is an alternative to ArduinoISP. But it is just a plain-old (large) sketch. Load it in the Arduino IDE; just like you would load any other sketch. Upload it to your Uno. Connect a capacitor across RESET and GND to disable auto-reset. Voilà. Your Uno is now a programmer. You still use "ArduinoISP" as the programmer.

TinyISP has several compile-time options available including an option that causes the Uno to output a "tuning signal" for Tiny Tuner 2.

I may have this installed wrong because it shows up under examples instead.

Good enough. As long as you can load the sketch in the IDE, compile it, and upload it, you are good to go. Just use "ArduinoISP" as the programmer.