Actually, this project is so simple that I really hesitated for a while before publishing it. Totally surprising: you don't even have to modify the fuse settings. This is a test for single step operation for Open Smart UNO R3. I used this module that is offered at Ali Express and may be others. It is named OPEN-SMART Blue DIY ATmega328P Development Board Module CH340 Driver with Buzzer LED Button + USB Cable Compatible for Arduino. It is offered as DIY or ready for use.
If you don't have such an OPEN-SMART UNO R3 you might use a standard Arduino-UNO where you can insert a socket for the crystal. The first Arduino-UNOs where shipped with through-hole crystals which can easily get removed. To remove an SMS crystal is not so easy, take care.
A third option is the usage of an ATmega328 on a breadboard and program it via ISCP. You will need a pullup resistor for the button.
You cannot use an UNO R4 because it has no crystal.
Place a 6-LED-module to pins 8 to 13 + GND, or, if you don't have this module, connect six LEDs to pins-8 to 13. You need only one resistor to GROUND.
If you don't have the OPEN SMART you also would need an external button.
Running-LightThe program provided below performs a running light which is much too fast to see when driven by a 16 MHz crystal. After uploading it remove the crystal. The processor will immediately stop execution and only one of the LEDs will be switched on.
Now connect pin-2 (= button K3) to the left crystal pin which is connected to ATmega328-pin 10 (not digital-pin-10), the green wire shown in the picture above. Then use button K3 for single-stepping through the code. Each of the commands inside the loop function takes only one machine instruction. By now, the running-light will run very slowly. Notice that after the LED at pin-13 is on it takes another five steps to switch the LED at pin-8 on again. That is because some instructions are performed to repeat the loop. After thousands of steps, the counter of Timer0 will reach its limit to update millis and micros. Possibly, your button may bounce and send more than one pulse to the crystal input at a time.
Another option is replacing the original 16 MHz crystal by a faster or a slower one if you got one of these. Values between 2 MHz and 25 MHz (overclocking) should work. You will recognize the difference of performance.
If you press the reset button or interrupt the power supply you better insert the crystal otherwise the processor at first has to perform the setup function and never reaches the loop function.
Before you can upload another program you have to re-insert the 16 MHz crystal. If your program contains more complex functions, a huge number of steps will be necessary to see the results.
void setup() {
pinMode(2, INPUT_PULLUP);
DDRB = 0xFF;
}
void loop() {
PORTB = 1;
PORTB = 2;
PORTB = 4;
PORTB = 8;
PORTB = 16;
PORTB = 32;
}
This
is the sketch for the breadboard version:
void setup() {
DDRC = 0xFF;
}
void loop() {
PORTC = 1;
PORTC = 2;
PORTC = 4;
PORTC = 8;
PORTC = 16;
PORTC = 32;
}
Practical ExampleNow let us connect the "device under test" (DUT) to a second Arduino, called TESTER. On the DUT, upload the well-known sketch "Blink.ino". The TESTER will send clock pulses until the DUT starts the loop-function, where the LED_BUILTIN gets set to HIGH. After detecting this HIGH the TESTER will stop sending clock pulses and print how many clock pulses it has sent.
The following connections have to be made:
TESTER pin-12 --> DUT RESET
TESTER pin-7 --> DUT Xtal (ATmega-pin-10)
TESTER pin-8 <-- DUT pin-13, LED_BUILTIN
This ist the code for the TESTER:
/*
device under test (DUT): Blink.ino
naked ATmega328
1. trigger reset
2. send clock pulses until DUT blinks
*/
byte clock = 7;
byte reset = 12;
byte stop = 8;
void setup() {
Serial.begin(9600);
Serial.println(__FILE__);
pinMode(clock, OUTPUT);
pinMode(stop, INPUT_PULLUP);
invokeReset(); // veranlasst RESET auf zweitem ATmega
Serial.println("start");
long count = 0;
while (digitalRead(stop) == LOW) {
takt();
count++;
}
Serial.print("clock count: ");
Serial.println(count);
}
void loop() {}
void invokeReset() {
pinMode(reset, OUTPUT);
delay(10);
digitalWrite(reset, HIGH);
}
void takt() {
digitalWrite(clock, HIGH);
digitalWrite(clock, LOW);
}
My results were: after 143173 clock pulses the DUT LED will be switched on.
Comments
Please log in or sign up to comment.