3

Is there a way to repurpose the reset button for the code, like an on-board button? I don't need it to reset, but it would be useful to make it run through a list of RGB LED cycles.

  • 1
    You can store the current state in EEPROM, and detect when the board has been reset (there is a special register for it). So at startup you load the state back from the EEPROM and see if a reset has occurred. If so select te next pattern (and save that to the EEPROM). – Gerben Dec 17 '16 at 13:38
7

If you just want the reset button to change the program mode, the simplest thing would be to let the button reset the Arduino and switch modes each time your program restarts. Then you do not need to change the fuses or get a high voltage programmer. The code would look like this:

void setup()
{
    // At startup, switch to the next mode.
    if (++mode >= NUMBER_OF_MODES) mode = 0;

    // etc...
}

There is just a small issue here: when the program starts, all the global variables (like mode above) are supposed to be initialized by the C runtime. This can be avoided by using a non-standard feature of gcc: if you request the variable to be stored in the special .noinit section, then it will not be initialized. Here is the program I used to test this idea:

const unsigned int NUMBER_OF_MODES = 5;

__attribute__((section(".noinit"))) unsigned int mode;

void setup()
{
    // At startup, switch to the next mode.
    if (++mode >= NUMBER_OF_MODES) mode = 0;

    Serial.begin(9600);
    Serial.print("Current mode: ");
    Serial.println(mode);
}

void loop() {}

Now, each time I press the reset button, it goes to the next mode among (0, 1, 2, 3, 4). The main drawback compared to using a regular input is the delay added by the bootloader, which is slightly more than one second.

A word about the cold boot initialization: the RAM is not initialized by the hardware and contains essentially random bits. This means you cannot count on mode having initially a valid value. This is why:

  • I am testing for ++mode >= NUMBER_OF_MODES rather than ++mode == NUMBER_OF_MODES, as the initial mode could be way larger than NUMBER_OF_MODES
  • mode is an unsigned integer, otherwise I would need to also test for it being negative.
2

Reset button is connected to the reset pin of Atmega328P-PU. So, when you press that button, the reset pin gets a LOW, which resets the chip!

Here is the thing, yes, you may disable the reset pin to use it as general I/O. However, if you disable it, you will not be able to reprogram your Arduino anymore! You'll effectively brick your Arduino...

By the way, yes you do need it to reset. When you program your arduino, the IDE sends a reset command from your PC via USB to reset your Arduino. When Arduino is resetted, bootloader looks for an incoming sketch, which is provided by the IDE and so on....

1

As noted in other answers, if you re-purpose the reset pin, PC6, by programming the RSTDISBL fuse, then some of the usual methods of loading a program into flash memory are made unavailable. Specifically, the usual serial-port programming using Arduino's Optiboot depends on the chip resetting upon demand. So does ISP programming, as done for example using a USBasp or similar device.

However, parallel programming remains available. This requires an STK500 or similar, or can be simulated using another Arduino.

Here are a couple of references from Atmel's doc8271 datasheet for ATmega48A/PA/88A/PA/168A/PA/328/P:

§14.3.2 Alternate Functions of Port C
“When the RSTDISBL Fuse is programmed, this pin [PC6] functions as a normal I/O pin, and the part will have to rely on Power-on Reset and Brown-out Reset as its reset sources. ...”

§28.6 Parallel Programming Parameters, Pin Mapping, and Commands
(Describes Parallel Programming wiring and protocol)

As it can be inconvenient having to hook up a parallel programmer to load new programs, instead of programming the RSTDISBL fuse you could modify the hardware. You would cut the trace from the reset switch close to the switch (for example, lightly touch the trace with a fast-spinning 1-mm drill bit, using a small Dremel or drillpress), then run a fine jumper wire from the switch or its trace to an input pin.

This method leaves all the other reset-circuit stuff (pullup resistor to 5V, capacitor to DTR) in place so that ISP programming would work without change.

0

I concur with everything Maximus has said.

It is possible - you can change the reset pin to be a normal I/O pin.

To do so you will need to program one of the ATmega328P's fuse bits. For that you will need an ISP programmer like the AVRISPmkII or Atmel ICE. You will also need a program such as Atmel Studio or AVRdude.

The reset disable fuse is part of the high byte fuses. First you will need to calculate high fuse. I use eleccelerator Fusecalc for this

Based on my boards.txt file, the default for the high fuse on the Arduino Uno is DE. Adding the reset disable fuse makes it 5E.

Program the fuse using Atmel Studio or AVRdude using your ISP programmer.

Complete Fusecalc settings

0

The other answers weren't working for me (on an ATmega168), but I found this solution:

const unsigned int NUMBER_OF_MODES = 5;
int * mode;

void setup() {
    mode = (int *) malloc (sizeof (int));

    // At startup, switch to the next mode.
    if (++(*mode) >= NUMBER_OF_MODES) (*mode) = 0;


    Serial.begin(9600);
    Serial.print("Current mode: ");
    Serial.println((*mode));
}

output:

Current mode: 0
Current mode: 1
Current mode: 2
Current mode: 3
Current mode: 4
Current mode: 0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.