How to down size to an appropriate chip?

So my code is the way I want it. The sketch was produced and tested using a UNO but I only ended up needing 8 IO pins (4 PWM) and no analogue. My sketch is a mere 4,000 bytes.

I really don't want to put that huge chip on the board if I can avoid it so where do I go from here? How do I port this sketch to a smaller chip. (Granted the sketch will require some pin reassignments).

The only thing I have right now to program with is the UNO so certainly that will need to be replaced with some other transfer method that accepts whatever chip I go to. I'm sure to face this again in the future so I'd like to set up now to be able to program various chips.

  • How to select an appropriate chip to downsize to?
  • How do I get my sketch into that chip?

Would the Tiny family be the way to go here?

The Tiny 84 is a 14 pin chip with what you require in terms of flash, PWM and I/O pins. You can use your Uno as programmer (using arduino as ISP program). Is 500 bytes of SRAM enough?

The most important issue is how much the code is ATmega328-specific, and this specificity is implied in many, many Arduino functions and libraries.

While there are ways to compile Arduino code for ATtinys, it doesn't mean each and every Arduino sketch will work on these correctly, or work at all.

So, how chip-independent is your code? Does it use Serial? Does it include some advanced Arduino libraries? etc.

The ATtiny84 might indeed fit the bill.

As for code specific to the 328 I don't know (limited experience here). The sketch is simple as you can see. It could certainly be reduced in size even further by an experienced programmer I'm sure.

How much RAM is required for a small sketch like this?

The sketch doesn't require any special lib inclusions to work. Basically it's blinking a couple of LED's, monitoring a PG signal from a regulator, the position of 3 switches and outputting a couple of different tones on demand.

I have lines for Serial.print() in the code but strictly for debugging while bread boarding. This is not necessary for operation and are currently commented out. I'm using INPUT_PULLUP on two pins. Don't know if that matters.

The ATtiny84 seems to have the required pins. Things get fuzzy after that as to what else is required to port the sketch to that chip. Will I need to include any extra libraries from the IDE to run the Tone() function for example?

/*Dual Transceiver Interface ver 6.0
Sketch version 6.0.1
Control code for:
   - Bi-color power LED indication
   - Transmitter selection
   - Audible alerts of transmitter 2 selected
   - Audible low battery alert
   - Alert cancel and Alert off functions
Created By Kirk Sceviour
08 Feb 2015
*/

boolean battchange = false; //remains false until a change is detected
boolean powergood = true;  //power supply is good
boolean cncl = false; //true for an interval when cancel button pressed
boolean discard = false;  //discard all alerts while true
boolean txtwo = false; //transmitter two selected

#define ALERTOFF 5 
#define CANCEL 12
#define TXSEL 8
#define redLED 10 
#define greenLED 9
#define AUDTONE 6
#define SWCOMM 7
#define PG 4


//for blink without delay functions
#define LED_ON 400     //blink interval millis
#define LED_OFF 3000
unsigned long ms;        //time from millis()
unsigned long msLast;    //last time the LED changed state
boolean ledState;        //current LED state

//for audible functions
unsigned int beepFreq = 440; //frequency of beep
unsigned long beepTime = 200; //duration of beep

//low battery audible indication
unsigned long msBeep;//time from millis()
unsigned long msBeepLast;//last time of beep
unsigned long battBeepPause = 120000; //time between battery beeps 

//comm 2 audible indication
unsigned long mstxBeep;
unsigned long mstxBeepLast;
unsigned long txBeepPause = 40000;//time between beeps (normal = 40000)

//for alert cancel function
unsigned long msCncl; //time from millis()
unsigned long msCnclLast;
unsigned long cnclTime = 100000; //duration of cancel mode 

void setup()
{
    pinMode(CANCEL, INPUT_PULLUP); //Cancel button. LOW when pressed
    pinMode(ALERTOFF, INPUT); //To Alerts Off switch. LOW when selected off
    pinMode(TXSEL, INPUT_PULLUP);  //To TXSEL switch. LOW indicates COMM 2 selected
    pinMode(redLED, OUTPUT); //Red power low indication
    pinMode(greenLED, OUTPUT); //Green power good indication
    pinMode(SWCOMM, OUTPUT);//Output to selector IC. HIGH switches to COMM 2
    pinMode(PG, INPUT); //Active LOW PG signal from regulator
    pinMode(AUDTONE, OUTPUT); //PWM output to mixer
  //  Serial.begin(9600); // for debugging
  
  //place unused pins here set to INPUT_PULLUP
  
  
 }
void loop()
{
 msBeep = millis();//time returned from milliseconds
 mstxBeep = millis();
 msCncl = millis();
 ms = millis();
 noTone(6);
  
//read transmitter selector switch
if (digitalRead(TXSEL) == LOW)
    {
    digitalWrite(SWCOMM, HIGH);//output to selector IC
        txtwo = true;//on comm 2
    txBeep();
    } 
    else
    {
    digitalWrite(SWCOMM, LOW);
        txtwo = false;
         }

  if (digitalRead(CANCEL) == LOW) //cancel button pressed
   {
    cncl = true;//cancel alerts
    //Serial.print("  Alerts Cancelled  ");
    }
    //check time elapsed since last event
    if (msCncl - msCnclLast > cnclTime) 
    {
    cncl = false; //allow alerts if time is up
    msCnclLast = msCncl; //set up for next event
    }  
    
//check the No Alerts switch and Cancel modes
 if (digitalRead(ALERTOFF) == HIGH || cncl == true)
        {//alerts are off or cancel mode active
        discard = true;//discard any audible alerts
        } 
    else  
        {//allow alerts
        discard = false; 
        }

//blink the correct LED 
 if (digitalRead(PG) == HIGH)//power good
        {
        digitalWrite(redLED, LOW);//trap red if on
        blinkgreenLED();
        powergood = true;
        }
     else//low battery detected
        digitalWrite(greenLED, LOW);//trap green if on
        blinkredLED();
        powergood = false;//low battery
        lowbattBeep();//send an audible alert
   }
   
//generate comm 2 audible alert  
void txBeep(void)//
{ //check comm 2 selected and cancel mode not active
  if (txtwo == true && discard == false) 
    {
   if (mstxBeep - mstxBeepLast > (txBeepPause))//check interval
      {//present a double beep
       //   Serial.print(" on Comm 2  ");//debugging
          tone(6, beepFreq, beepTime); //output tone
          delay(250);
          noTone(6);
          tone(6, beepFreq, beepTime);
          delay(250);
          noTone(6);
          mstxBeepLast = mstxBeep;  
        } 
    }
  }
//generate low battery audible alert
void lowbattBeep(void)
  {//check if first indication
  if (digitalRead(PG) == LOW && battchange == false) 
      {//new indication of low battery 
     //   Serial.print("  low batt detect  ");//debugging
        battchange = true; //change the battery state
      }
   if (digitalRead(PG) == HIGH && battchange == true) 
        {//spurious indication so reset.
         battchange = false; // reset batt status
         noTone(6); //make sure the pin is off
     //    Serial.print ("  batt status reset  "); //debugging
         }
   if (digitalRead(PG) == LOW) 
     { //check time since last beep
     if (msBeep - msBeepLast > (battBeepPause)) 
        {// Serial.print("  low batt audible alert  ");
          tone(6, beepFreq, beepTime); //play
          delay(200);
          noTone(6);
          tone(6, 250, beepTime);//play lower tone
          delay(200);
          noTone(6);
          msBeepLast = msBeep;  
        } 
      }
  }

// LED blink functions. All other code above this.
void blinkgreenLED(void)
  {//determine the last time the LED was on
if (ms - msLast > (ledState ? LED_ON : LED_OFF)) 
    {
    //switch states if necessary
    digitalWrite(greenLED, ledState = !ledState);
    msLast = ms;
    }  
  }
void blinkredLED(void)
  {
if (ms - msLast > (ledState ? LED_ON : LED_OFF)) 
     {
     digitalWrite(redLED, ledState = !ledState);
     msLast = ms;
     }
  }

It does seem pretty simple - but indeed, it's worth to check whether millis() and tone() are implemented correctly for ATtiny before you go any further. I suspect tone() will be problematic.

For the files needed to convert Arduino sketches for ATtinys, see here: http://highlowtech.org/?p=1695

CopperDog: I really don't want to put that huge chip on the board if I can avoid it so where do I go from here? How do I port this sketch to a smaller chip. (Granted the sketch will require some pin reassignments).

That suggests to me that there is enough space for an Atmega 328 and, if so, I can see very very little benefit from all the trouble involved in changing to a physically smaller chip. It's not as if the 328 is very expensive.

I presume you are not planning to make hundreds of devices so that the cost saving might be significant. And if I was I think I would go for one of surface mount 328 variants - they are very small, if size is what matters.

...R

Robin2: That suggests to me that there is enough space for an Atmega 328 and, if so, I can see very very little benefit from all the trouble involved in changing to a physically smaller chip. It's not as if the 328 is very expensive.

I presume you are not planning to make hundreds of devices so that the cost saving might be significant. And if I was I think I would go for one of surface mount 328 variants - they are very small, if size is what matters.

...R

I am also working on a project in which I want to use an Ardunio on a PCB. The ATTiny85 does not have enough pins, so I was looking at the ATTiny84.

However, when I tried to buy some on Ebay I found they are both scarce and expensive. It has made me consider using an Atmega chip as they are a lot more plentiful on Ebay and comparatively priced to the ATTiny84.

Not sure about power consumption of the ATTiny84 vs an ATMega, which is a consideration for me in determining which ATMega to use, since I will be using battery power.

Plenty of Attiny84’s at Mouser:
http://www.mouser.com/Search/Refine.aspx?Keyword=attiny84
Just a couple bucks for shipping, no sales tax, and will not take 3 weeks for delivery.

igendel: It does seem pretty simple - but indeed, it's worth to check whether millis() and tone() are implemented correctly for ATtiny before you go any further. I suspect tone() will be problematic.

Yeah these are exactly my concerns. I don't have enough programming experience to know whats a definite non starter when it comes to this. I'll try to find out.

Robin2: That suggests to me that there is enough space for an Atmega 328 and, if so, I can see very very little benefit from all the trouble involved in changing to a physically smaller chip. It's not as if the 328 is very expensive.

I presume you are not planning to make hundreds of devices so that the cost saving might be significant. And if I was I think I would go for one of surface mount 328 variants - they are very small, if size is what matters.

...R

There isn't much space which is what lead me to think of down sizing. The surface mount package was my original plan however then the sketch can't be altered easily. Speaking of which, I'm guessing a breakout board is required to program the SMD version of the 328. Is that correct?

It would be a real pain to have to physically change a chip for a minor code change. Do most people design the PCB's to allow on board programming then?.

OK. Looking at a Breadboard Arduino schematic and there really isn't much to it. I should be able to incorporate this into my existing project by soldering a surface mount 328P to the board with the associated crystal, load caps etc and just upload straight to the chip that way via a 6 pin header

I'll need a surface mount chip with the boot loader on it I realize and an FTDI cable. If I'm reading this correctly I should then be able to simply connect my board directly to the IDE via the FTDI and upload at will.

Any reason that won't work? Almost sounds to simple.

CopperDog: The surface mount package was my original plan however then the sketch can't be altered easily.

Why do you think this? For the most part, just route the TX/RX pins (plus a couple others, IIRC) to a header - and use a USB to FTDI serial cable (or similar).

Ideally, for a finished product (if it isn't meant to be user altered/upgraded) - you'd just provide a couple of pads instead of a header, and then have a pogo pin jig or something similar to make contact with the pads.

I see I came to the same conclusion just before you posted cr0sh. Thanks for the input. This is exactly what I’m going to do.

It’s my first project incorporating an MCU. Am I correct in saying I need a boot loaded chip?

If so do you have any suggestions on where to obtain a boot loaded 328P in surface mount? Adafruit only seems to carry the DIP versions

CopperDog: If so do you have any suggestions on where to obtain a boot loaded 328P in surface mount? Adafruit only seems to carry the DIP versions

You can load the bootloader to a surface mount chip using an Uno just as you can with a DIP version. I used this tutorial.

...R

If you have the ICSP pins available (ie. nothing else dragging them down) then you don't need a bootloader on the chip. Just an ICSP programmer, which can be a UNO.

MorganS: If you have the ICSP pins available (ie. nothing else dragging them down) then you don't need a bootloader on the chip. Just an ICSP programmer, which can be a UNO.

I didn't see this last post until today. Isn't the bootloader required to be on the chip to interpret the uploaded sketch from the IDE? I'm partway through my board design and need to sort this out before going further.

It's my understanding that if I place ICSP and FTDI headers on the board I can hook stright to the chip using an AVR USB programmer. That would let me burn any bootloader or upload any program to the chip. For example, if I want to switch the chip over to a BASCOM designed program from the Arduino sketch currently on it I coud do it in the field. Having the headers would also let me put a bare SMD chip on the board, hook up an ISP to the ICSP header, burn the bootloader, hook up the FTDI and upload the sketch I have ready to go into my little TQFN 328

Am I wrong here?

Maybe I've been reading to many different articles. I thought I had this.

If I put an ICSP header on the board do I need the FTDI header?

Will the ICSP hookup let me write everything I need to a bare chip using an AVR USB programmer and any IDE supported by the programmer?

The bootloader receives the compiled sketch and loads it into memory. After a reset, the bootloader checks to see if another upload is being started from the PC, and if not it kicks off the sketch.

If the compiled sketch is loaded directly into memory by a programmer, the bootloader area is overwritten and the sketch starts immediately after the reset. Burning the bootloader first will set the fuses for correct operation (say 16 MHz external oscillator) is a 1-time operation, then the sketch can be uploaded via programmer. Forgetting to set the fuses can result in a slow running program (8 MHz internal oscillator with system clock divided by 8, so 1 MHz system clock speed vs 16 MHz).

I put both headers on my boards for max flexibility later on.

Excellent. That was my plan. I'll carry on thank you for the help.

Why downsize to another chip? Is it for cost (mass production?), power, size or what?

When I get an entire Pro Mini board (168) for 4$, that's cheaper than any homebrew solution with a more crippled chip. And it fits most stand-alone applications. For programming I've wired an IC adapter, replacing the MPU on my UNO board, and connect it to the Mini board for development and tests.

Mostly for size. This chip will be used in a communications device to provide audible alerts to the user. The alerts will be mixed with regular audio traffic. The whole board is about the size of a 9 volt and is nearly all SMD. There isn't much room if I want to use the same enclosure.

I also have plans for future projects that are size limited.