TinkerCAD Arduino simulation freezes, prints " ÿ " in monitor

I have a pretty ambitious Arduino project for a newbie that uses LEDs to illustrate traffic flow on a physical intersection model.

I'm using TinkerCAD to make a mock-up before I make the real one. Photo of TinkerCAD attached. The strips are the roads, and each tile lights up when a simulated vehicle is occupying it. The tiles are class objects that have an integer location and a boolean occupied status that vehicles will read before advancing to it. The vehicles are also class objects with variables and functions of their own and they're created the same way as tiles.

I'm having an issue where after the tile objects are created, the program freezes while assigning location values to the tiles and outputs "ÿ" in the serial monitor. See screenshot.

At first I wondered if it was a memory issue, but nothing I do with optimizing code has had any effect. The error happens in the same place every time. I've also done some math and I don't think I should be reaching the memory limit yet, though I don't know how that works in TinkerCAD.

I also tried splitting the for loop into smaller chunks, but that didn't have any effect either.

If I shrink the NUM_TILES value to 100-200 the program will advance to the next chunk, but then freezes mid print in the console when it's adding values for the vehicle objects (without the weird ÿ, interestingly enough).

Like I said, I'm new to Arduino and coding, so I'm not super familiar with the more advanced aspects like memory overflow, pointers, objects, etc. I just know enough to be dangerous. Any help is appreciated.


Relevant code excerpt below:

#include <Adafruit_NeoPixel.h>

#define RED 255,0,0
#define GREEN 0,255,0
#define BLUE 0,0,255
#define YELLOW 100,100,0
#define WHITE 100,100,100
#define NUM_TILES 292
#define STRIP_OUT 2

Adafruit_NeoPixel Strip1(NUM_TILES, STRIP_OUT);

class Tile
{
private:
  short int  _location;
  bool _occupied = false;
  
public:
  Tile(){}
  void setlocation(short int location){_location = location;}
  bool checkoccupied(){return _occupied;}
  void occupy(){_occupied = true;}
  void vacate(){_occupied = false;}
};

void LEDRed(int bulb){
  Strip1.setPixelColor(bulb, RED);}
void LEDGreen(int bulb){
  Strip1.setPixelColor(bulb, GREEN);}
void LEDBlue(int bulb){
  Strip1.setPixelColor(bulb, BLUE);}
void LEDYellow(int bulb){
  Strip1.setPixelColor(bulb, YELLOW);}
void LEDWhite(int bulb){
  Strip1.setPixelColor(bulb, WHITE);}

Tile *tile = new Tile[NUM_TILES];

void setup()
{
  for(int i = 0  ; i < NUM_TILES; i++){tile[i].setlocation(i);} // Freezes during this step.
  Serial.print("\nTile Setup Complete");
}

The "funny Y" is character 255 (-1). Usually you get that when a function fails.

Edit: ...Or returns "no characters available"

1 Like

Are you using an UNO like in the picture? You are probably running out of RAM. You've plopped almost 1500 bytes on the stack and you've only got 2000 to work with. Plus you have the Neopixels library there that's probably using a significant chunk.

2 Likes

The actual project will use a Mega, so this might not even be an issue at that stage. Still, I'd like to have a working mock-up before I move ahead.

If RAM is the issue here, is there any way to cut down on usage aside from just having less objects? I thought RAM was only temporarily used during a for loop or such and cleared after the loop terminated, hence why I tried to break the loop down before.

Global objects are also in RAM. The 292 Tile objects you create each need at least three bytes each of RAM that I see.

I don't know how much neopixel uses.

1 Like

Tinkercad does not have a Mega board, but Wokwi does: https://wokwi.com/projects/new/arduino-mega

Does Arduino use a similar Stack/Heap system like C++ on a PC would? Could moving things to the Heap free up RAM?

No. This is a completely different world. Your program space and your RAM space are completely separate. The heap and the stack both share the 2K of available RAM. The heap grows from one end and the stack grows from the other. If the two ever meet then you have a problem.

1 Like

It is a start:

The ledstrip is connected with an invisible data line. Just start the simulation.

Do you really need the class ? Print in the Serial Monitor how much memory space it uses.
In the Arduino world it is better to keep it as simple as possible.

2 Likes

think about if you really need a separate class to store the _location and _occupied (3 bytes * NUM_TILES) on top of the information you have already in your strip (also 3 bytes for each tile). May be a black tile is not occupied already?

I have a "traffic simulation" with 256 pixels running on an Uno and still some free resources:
https://werner.rothschopf.net/microcontroller/202105_arduino_traffic_city_en.htm

1 Like

One reason I decided to use the class system for tiles is that, when I started coding this, I didn't know how the Neopixel library worked behind the scenes, and didn't know how to utilize its contents. I used the tools that I understood, and those tools are what you see in the post.
Now that I've looked through the library a few times I'm seeing that there are indeed ways to use what's included there already. I'll play around with it and see what happens.
The next hurdle will be shrinking the size and number of vehicle objects, since that's the next place I'll run out of memory. Maybe I can do something similar with that.