ATMEGA48 confusing behaviour when PD2 +ve

This seems to be the kind of thing that must have come up before but I can't find any reference so maybe someone here will recognise the symptoms and point me in the right direction!

I have a little project I developed to flash 8 LEDs so they make words as they move. It seemed to work on the arduino so I thought I would make a prototype using an ATMEGA48 chip (cheaper and enough memory). I managed to program it ok using the arduino as a programmer and it seems to run ok.. However I have a tilt sensor attached to PD2 (INT0) so that the chip can go to sleep after a while then be woken up. I have found that if PD2 is at 0V everything is OK, if set to 4.1V all the LEDs flicker (are on but at low and different brightnesses) and the program restarts once PD2 drops back to 0V. After doing this a few times it 'gets stuck' (all LEDs flicker when PD2=+, none when PD2=0) but runs ok again after grounding reset or powering down.

Supply voltage doesn't change visibly when the tilt switch opens and closes. I'm using a hand soldered surface mounted chip so, although everything seems to be connected with no shorts, it's not impossible that the chip got hotter than it should. Would that cause this behaviour? I understand that the fuses in the boards.txt only get set if a bootloader is used, might there be something in the default behaviour of the atmega48 that is causing this behaviour and I need to override? (If so how? (When I first powered up the chip, before managing to upload the sketch, all the LEDs flicked in the same way they do when DP2 is +ve) Is my wiring just wrong? I have defined DP2 as input in my sketch

see here for the addition to the boards.txt, sketch and wiring diagram

I have found that if PD2 is at 0V everything is OK, if set to 4.1V all the LEDs flicker (are on but at low and different brightnesses) and the program restarts once PD2 drops back to 0V.

…usually indicates that the processor is constantly resetting. This could be caused by… software bug; RESET pin not held high; short-circuit through the processor.

These two are mutually exclusive…

set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
attachInterrupt(0,wakeupNow, CHANGE); // use interrupt 0 (pin 2) and run function

If the processor is ever put to sleep, it will only wake from a reset or power-up. So, it is very unlikely that the sleep code is causing the problem.

Given the symptoms, I suggest you first very carefully check for wiring problems. Then, run very simple test sketches (e.g. toggle one LED when the tilt switch changes state; turn on a single LED) checking for anything getting hot.

Are the LED series resistors really 22 ohms?

Why did you include the 100K resistor in parallel with the tilt switch?

Very wise, thank you for replying. I was slightly wrong-footed by managing to program the chip at all so easily, I had expected more headaches than I actually encountered.

  • Connecting the reset pin to Vcc doesn't seem to fix it (sadly, that would have been rather simple). So it's probably not a simple short directly from PD2 to RESET either internally or externally. Besides it works the other way round, it resets when PD2 is high so it would have to be an internal short to some other part of the processor. Like I said I could have damaged it and they're cheap enough and I have spares so I could possibly try a different one.
  • The sleep and wakeup work fine (though if PD2 is connecting to the RESET in some way this would still be the case. I have used the identical code on standard Seeeduino and ATMEGA328s with a button on PD2 with no problem (though haven't tried holding the button down, will do that now!)) When I comment out that whole section it doesn't have any impact on this problem.
  • Good idea about the simple sketch. Will do.
  • LED datasheet says they will take 30mA with forward 3.8V Atmels datasheet says 40mA per pin subject to total 200mA so if all LEDs on that's 25mA. i.e 0.6V drop across 22ohm and my supply is 4.4 dropping to 3.something as the batteries flatten.
  • 100k just stuck on while I was trying to figure out the problem. Grasping at straws. More logical to have put it between the RESET and Vcc!

Nothing feels to get hot (using my bottom lip as thermometer) even after leaving it for a while on LEDs, resistors or processor.

Thanks again for your input.

If you can, swap the 100K resistor (the one parallel to the tilt switch) with a 10K resistor. The voltage at PD2 should be 1/2 VCC. Is it?

Well nearly, it's a bit higher than predicted by a simple R2/(R1+R2). The 10k is really 10.02k and the one I swapped for the 100k is 9.91k but the voltage on PD2 is 0.53Vcc so that works out at the equivalent of 71.5k inside the microprocessor between PD2 and the supply. Is that about right for pinMode INPUT?

Another thing I have noticed is that although it starts off being pretty much like a reset, after a while it 'gets stuck' and no amount of making and breaking the tilt-switch will get it working again. However grounding RESET then does restart it ok. I suppose that's not so surprising as, in my previous ramble, I had worked out that it isn't simply a direct connection to the RESET but something more complicated.

I have programmed the chip using the arduino as ISP and not uploaded a bootloader (I understand there is not separate memory space on the 48) Is everything sorted out by the compiler with respect to setting up the interrupts? I can't see anything in atmel's manual that could mean + on PD2 triggers some kind of restart, but there could be something in those 377 pages!

Well nearly, it’s a bit higher than predicted by a simple R2/(R1+R2). The 10k is really 10.02k and the one I swapped for the 100k is 9.91k but the voltage on PD2 is 0.53Vcc so that works out at the equivalent of 71.5k inside the microprocessor between PD2 and the supply. Is that about right for pinMode INPUT?

Did you run the test with the processor powered and running?

Is everything sorted out by the compiler with respect to setting up the interrupts?

While I do not have experience with the ATmega48 processor, for all the other processors I’ve used the compiler does sort out setting up the interrupts.

Did you run the test with the processor powered and running?

Yes. Soldered in, so hard to test otherwise. Remeasured the resistors also voltages when firsts starts and after it 'got stuck' and it's a bit nearer to Vcc R2/(R1+R2) but still off (at best equivalent to 200k internal impedance PD2 to Vcc)

I'm not sure how the compiler uses the boards.txt, i.e. does it ignore the if haven't uploaded a bootloader or does it include some code to set the fuses. I was just thinking that there might have been something in the bootloader addition to the 168 or 328 that might have set fuses differently from the default 48 settings. The only thing I can see (apart from internal clock and boot size/reset) is that I haven't set brown-out whereas this is set to 2.7V on the 328 and 168. I wouldn't expect this to cause the observed behaviour.

If I get a chance later I will put on a little sketch to switch one LED on and off with the tilt switch. Will post the results.

Quick test sketch using input on PD2 and just switching on and off LEDs in order resets whenever PD2 changes low to high. If I keep PD2 grounded and use input on PD3 then it seems to work as expected and doesn’t reset. Allowing PD2 to go high resets the program.

Interestingly if PD2 goes high fleetingly (i.e. tilt switch only just opening) all the LEDs flicker as before but the sequence does not re-start. i.e. the value of the variable for which LED to switch next is remembered. However it does increment as if PD3 had been set high!!

Maybe the next step is to try a different chip?

const int pinIn = 3;
const int pin0 = 4;
int offSet = 0;
boolean flipFlop = false;

void setup() {
  pinMode(pinIn, INPUT); 
  for (int i=0; i < 7; i++)
  pinMode(pin0+i, OUTPUT); 
//  digitalWrite(pin0, HIGH);

void loop() {
  int buttonState = digitalRead(pinIn);
  if (buttonState == HIGH && flipFlop == false) {
    digitalWrite(pin0 + offSet, LOW);
    flipFlop = true;
  else if (buttonState == LOW && flipFlop == true) {
    offSet = (offSet + 1)%7;
    digitalWrite(pin0 + offSet, HIGH);
    flipFlop = false;

As odd as it sounds, make sure you have solid power for VCC and GND.
I have experienced odd behavior with high resistance on the power lead.

smeezekitty, Yes. Dropping supply voltage was my first suspect (as I didn't think it could be anything to do with using the PD2) however the supply is good and near and when measured actually goes up when the LEDs flicker. With a .1uF capacitor across the supply I would have expected to see it drop if Vcc was dropping for long enough to restart it.

I have made up another circuit using a fresh atmega48 and it displays identical problem so less likely due to overheated/damaged chip.

I have disconnected the circuit from PD2 (in preparation for using PD3 as the wakeup pin instead as that didn't seem to give the headaches when I did the simple test) However the sketch now doesn't run at all when the batteries are in (half illuminated LEDs all the time) BUT when connected to the 5V from the arduino as avr for programming seems to run fine (eventually stops though, poss as it tries to sleep). So it looks like it might be something to do with power supply.

It runs on batteries fine if I ground PD2. Battery voltage 4.3V. Haven't changed the sketch yet to use PD3 and not look at PD2. Any ideas gratefully accepted!

Modified the sketch to use PD3 (int 1 rather than int 0) and kept PD2 grounded all the time and it all seems to work as expected. I’d still be glad of any ideas why.

I might try increasing the resistances on the LEDs as it doesn’t really need to be quite so blindingly bright and it might be getting quite near the 200mA limit when all the lights are on (and following CodingBadly’s intuition). Also make the batteries last longer. Though this wouldn’t have been an issue in the test sketch where I only switched on one LED at once.

It seems at this point either there is a serious hardware bug in the chip (unlikely) or the compile is inappropriately setting up INT0.
Have you tried the same code on another type of chip such as a atmega 328?

On the mega48 the interrupt vectors are rjmps whereas on the UNO it would be jmps. Take a look at the vector table.

Except that when I tried the simplified 'non interrupted' sketch above it displayed the same problem.

Other possible culprits:
Leaving the reset unconnected is a bit sloppy but it is pulled up internally so would probably give only very intermittent problems (if any).
When first connected for programming PD2 may be connected to 5V (through 10k, depending on whether tilt switch is open or closed) prior to setting as input or output but it would seem odd for this to break it.
8xI/O pins are connected to ground via 22ohm and 3.8V LEDs This should draw a manageable current with 4.3V supply but is on the top side while all are lit and definitely too high while connected to the programmer 5V! I think I'm settling on this as suspect #1

Trying to read thru the whole thread and make some sense I thought you said that everything works OK if you move the switch pin from PD2 to PD3. Only when using D2 does the problem show. Did I misinterpret?

If that is the case then would that not rule out a power supply issue? If the program and hardware work in one situation(using PD3) and not the other (using PD2) then would that not lead to it being a software issue ?

I could see if PD2 was set as an output and that pin is shorted that would cause a little weirdness specially if the brownout fuse is set. But you are just using it as an input.

I thought you also said that the program works with a 328 but when you switched to a 48 that is when the problem reared up. Stick a 328 on the board and see what happens. Maybe leave the bootloader out and just do what you did with the 48 and see what happens.

justone, well yes that's what I would have thought but I can't see it in my code. For instance this (entire sketch)

void setup() {
  pinMode(2, INPUT);
  pinMode(7, OUTPUT);digitalWrite(7, HIGH);
void loop() {}

doesn't work if PD2 is high. But is fine if I ground it. (I've tried it without the pinMode(2..)

So it could be something the compiler has created, or something left over from first uploading a sketch with an interrupt on that PD2. Though that latter doesn't really make sense as the symptom appeared as soon as the sketch was first uploaded on a fresh chip and the interrupt setup only happens after it's been running for a few minutes. In fact I am pretty sure that the interrupt isn't causing the problem. Still could be a high voltage on PD2 before the sketch had been uploaded (tried to keep it grounded but might have let the wire slip as the lights did flicker.) However it now connects to Vcc through a 100k resistor.

Don't think the brown-out is set by default on the ATMEGA48

I have increased all the resistors now as per the following non-working circuit:

and this circuit which works fine (have to change PD3 to input before setting interrupt and then to output as soon as it wakes.

Not a EE type but I don’t see why you have those 3 capacitors in series in your schematic.

Not enough experience with the arduino environment but under AVRStudio you should be able to see a list type file of the compile which would show what is being produced in the way of instructions. Do a little search here and see what pops up. The main thing is to see what code is being generated.

Also search the forums on how you can grab the hex file produced ( there is a certain keypress to this ) ( verbose ) .

When you get the hex file and/or list file post it.

Not a EE type but I don't see why you have those 3 capacitors in series in your schematic.

LOL, those are the symbols for three series battery cells powering the whole circuit. Note the unequal length of the two horizontal lines for each cell. Cap symbols use lines of equal length.



To be fair I have mangled some components from the Eagle library with a use-able footprint i.e. capacitor for tiltswitch!

I found the verbose option first attempt (shift+‘play’). The hex file means little and although I probably have a disassembler in amongst the AVR stuff, the assembler wouldn’t mean a great deal more! It takes this posting over the limit if I put it in a code box so I have saved it here:

and for completeness this is the hex file for the minimalist script above