I must confess: this article could and should have been written twenty years ago. But better late than never.
As you know, after reset the bootloader is performed. It is only a short moment, but if you remove the crystal and execute the code step by step it will take ages before the setup function will start. That is why I used a second Arduino to send high speed pulses to the crystal input, but reduced the speed as soon as the setup function starts. I removed the crystal and connected XTAL2 to pin-12 of that auxiliary Arduino which will send pulses at high speed to the main Arduino. In its setup function, pin-2 is set to HIGH, which is connected to the interrupt input (pin-2) of the auxiliary Arduino, which will reduce the pulse frequency to a lower value whatever you want. So, this is the setup function of the main Arduino
void setup() {
// force long delays:
DDRD = 4; // = pinMode(2, OUTPUT) but fewer steps
DDRD = 0;
/*
insert code to be examined and executed slowly
*/
}The code for the auxiliary Arduino is much longer:
const byte clock = 12;
const byte inSetup = 8;
const byte inLoop = 7;
const byte set = 2;
const int time = 500;
volatile boolean starting = true;
void setup() {
Serial.begin(9600);
Serial.println(__FILE__);
// visible control:
pinMode(LED_BUILTIN, OUTPUT);
pinMode(inSetup, OUTPUT);
pinMode(inLoop, OUTPUT);
digitalWrite(inSetup, HIGH);
// drive slave:
pinMode(clock, OUTPUT);
// enable ISR:
pinMode(set, INPUT_PULLUP);
EICRA = 2; // falling
EIMSK = 1; // enable ISR INT0
long count = 0;
// execute bootloader fast:
while (starting) {
digitalWrite(clock, HIGH);
digitalWrite(clock, LOW);
count++;
}
Serial.print("clocks before end of setup ");
Serial.println(count);
digitalWrite(inSetup, LOW);
digitalWrite(inLoop, HIGH);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(clock, HIGH);
delay(time);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(clock, LOW);
delay(time);
}
ISR(INT0_vect) {
// terminate setup
starting = false;
}Actually, it will count the pulses that had to be sent before the main Arduino will tell you that setup just has started.
As can be seen in the picture above, I used Arduino clones where you have access to the crystal and can easily remove it. The ones I used also offer three buttons which can be used to install more options. Of course, you also can use ATmega328P inserted in breadboards. There are five wires between both Arduinos: GND to GND (black), Vcc to Vcc (red), Reset to Reset (blue), pin-12 (Aux) to Xtal2 (main) (yellow), pin-2 (main) to pin-2 (Aux) (green). For some reason or another, I had to add a capacitor of some 100 pF connected to pin-12 (Aux) and GND, otherwise one pulse might lead to execution of two steps of the main Arduino. Maybe you need to play with the proper value of the capacitor.
In the breadboard version, it is more easy to use PORTC rather than PORTB, see the corresponding attachment. Make sure you use a high quality capacitor.
Obvioulsly, to upload code to the main Arduino, a 16 MHz crystal has to be inserted. Both Arduino can be operated by connecting only one USB cable to any one of them. As the reset pins of both Arduinos are connected it does not matter whose reset button you press in order to restart the system.
The example to examine was a simple running light, using a module with 6 LEDs and 6 resistors, inserted in pins 8 to 13 of the main Arduino. At each pulse, the next light is swiched on. When the last LED is on, an rjmp command is executed which needs two pulses.
This is what the auxiliary Arduino will print on the Serial monitor:
C:\Users\x\Documents\Arduino-alt\SINGLE_STEP\invoke1\invoke1.ino
clocks before end of setup 175687
Feel free to insert your own testing programs.
The attachments are:

_ztBMuBhMHo.jpg?auto=compress%2Cformat&w=48&h=48&fit=fill&bg=ffffff)





Comments