Arduino delay function not working with VS Code

I have #include <Arduino.h> at the top of my main file, but when I make a call delay(1000) in my code, it just freezes at that point.

The exact same code works in the Arduino IDE, so maybe the Arduino framework isn’t linking properly? What makes it weirder is that Serial.print(...) works just fine!

Does anyone know if I need to explicitly link against the Arduino framework or something?

It does work for me, so please share the minimal code snippet that demonstrates the problem, including platformio.ini file.

Platform.ini:

[env:atmega328p]
platform = atmelavr
board = nanoatmega328
framework = arduino

Code snippet:

#include <Arduino.h>

int main(void)
{
    Serial.begin(9600);
    while (1)
    {
        Serial.print("hi\n");
        delay(1000);
    }
}

 

"hi" only prints one time when I monitor it using the Serial Monitor in VS Code. When I run the exact same code in Arduino IDE however, it prints "hi" once every second as expected.

UPDATE: I updated Platform.ini (specifically the env parameter) to look like this:

[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino

And I still get the same issue that delay() just freezes the program…

The [env:nanoatmega328] just gives a name to your environment definition and has no impact on the actual configuration. The environment name just has to be unique across your platform.ini file as soon as there would be more than one environment definiton.

Since you are using the Arduino framework I suspect having a main function is not a good idea.
The Arduino framework just implements the main function behind the scenes and calls the setup() and loop() functions in your sketch / platformio main source file:

int main(void)
{
    setup();

    while (1)
    {
        loop();
    }
}

So you just have to implement a setup() and a loop() function:

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.print("hi\n");
    delay(1000);
}
1 Like

The above post is right. Do not overwrite the main function if you don’t need to.

There is more to the main() function: It initializes the Timer0 of the ATMega328P. This will cause an ISR to be called every millisecond which will update the elapsed milliseconds variable.

int main(void)
{
	init();

	initVariant();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
        
	return 0;
}
void init()
{
	// this needs to be called before setup() or some functions won't
	// work there
	sei();
	
	// on the ATmega168, timer 0 is also used for fast hardware pwm
	// (using phase-correct PWM would mean that timer 0 overflowed half as often
	// resulting in different millis() behavior on the ATmega8 and ATmega168)
#if defined(TCCR0A) && defined(WGM01)
	sbi(TCCR0A, WGM01);
	sbi(TCCR0A, WGM00);
#endif

	// set timer 0 prescale factor to 64
#if defined(__AVR_ATmega128__)
	// CPU specific: different values for the ATmega128
	sbi(TCCR0, CS02);
#elif defined(TCCR0) && defined(CS01) && defined(CS00)
	// this combination is for the standard atmega8
	sbi(TCCR0, CS01);
	sbi(TCCR0, CS00);
#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
	// this combination is for the standard 168/328/1280/2560
	sbi(TCCR0B, CS01);
	sbi(TCCR0B, CS00);
#elif defined(TCCR0A) && defined(CS01) && defined(CS00)
	// this combination is for the __AVR_ATmega645__ series
	sbi(TCCR0A, CS01);
	sbi(TCCR0A, CS00);
#else
	#error Timer 0 prescale factor 64 not set correctly
#endif

//lots of more stuff
}

If you overwrite main but don’t set that timer, you will hang up on a delay call because there is no timer set-up to update the ellapsed millisecond. It just waits there forever.

1 Like