Connect with us

Tic-Tac-Toe game

Discussion in 'Microcontrollers, Programming and IoT' started by bancroft, Jun 24, 2021.

Scroll to continue with content
  1. bancroft

    bancroft

    47
    1
    Apr 23, 2021
    A couple of days ago, I had a sudden flash of inspiration that maybe learning a new LCD needs to start with a simple and interesting project, so I put my previous project on hold and decided to make a tic-tac-toe game first.
    The same configuration as before, I have an LCD touch screen and an Arduino UNO, this is a newbie project, I uploaded the program to the board after I finished programming it, but that's when the problem occurred.
    Code:
    Arduino:1.8.12 (Windows 10), Development board: "Arduino Uno"
    
    The project uses 6336 bytes, which occupies (19%) of the program storage space. The maximum is 32256 bytes. data section exceeds available space in board
    
    Global variables used 3046 bytes, (148%) of dynamic memory, leaving -998 bytes for local variables. The maximum is 2048 bytes.
    There is not enough memory; visit the following URL to follow the instructions to reduce memory usage.
    http://www.arduino.cc/en/Guide/Troubleshooting#size
    Error while compiling for development board Arduino Uno.
    
    Turn on in File -> Preferences
    "Show detailed output during compilation" option
    This report will contain more information.
    How should I solve this problem?
     
  2. Bluejets

    Bluejets

    4,875
    1,018
    Oct 5, 2014
    Use an Arduino with more memory.
    Maybe a mega.
    You might be able to add extra memory but it appears you don't know how.
    If you visit the Arduino site I'm sure they will have many details there.
     
  3. Harald Kapp

    Harald Kapp Moderator Moderator

    11,533
    2,656
    Nov 17, 2011
    Upload your code for inspection.
    The "data section" is where the constant data of the program is stored. A typical reason for exceeding the available space is the excessive use of Strings in e.g. Serial.Println() statements which are often used for debugging.
    • remove (comment) all Serial.Print and Serial.Println statements that are not strictly necessary.
    • use PROGMEM to store large data sections. See also here.
    • Check the sizes (memory requirements) of your variables, especially of arrays. Use the smallest possible variable type where possible. Re-use variables if possible instead of creating new ones (e.g. loop counters).
    See also here.
     
    zain_sh likes this.
  4. bancroft

    bancroft

    47
    1
    Apr 23, 2021
    Thanks for the reminder that I should put up my code.
    Code:
    unsigned int r_flag1 = 0;
    uint8_t   RecievedTemp1[30]       = {0};
    
    uint8_t   cout_i = 0;
    unsigned int quan_hang1 = 0;
    unsigned int quan_hang2 = 0;
    unsigned int quan_hang3 = 0;
    unsigned int quan_lie1 = 0;
    unsigned int quan_lie2 = 0;
    unsigned int quan_lie3 = 0;
    unsigned int quan_zuoxia = 0;
    unsigned int quan_youxia = 0;
    
    
    unsigned int cha_hang1 = 0;
    unsigned int cha_hang2 = 0;
    unsigned int cha_hang3 = 0;
    unsigned int cha_lie1 = 0;
    unsigned int cha_lie2 = 0;
    unsigned int cha_lie3 = 0;
    unsigned int cha_zuoxia = 0;
    unsigned int cha_youxia = 0;
    unsigned int cha[8]={0};
    void setup()
    {
       Serial.begin(115200);
       for(int i=3; i<=8; i++)
       pinMode(i,OUTPUT);
    }
    
    void loop(){
    
      if(Serial.available() != 0)
      {
    //    for(cout_i = 0; cout_i < 30; cout_i ++)
    //    {
    //        //RecievedTemp1[cout_i] = Serial.readBytes(RecievedTemp1, 15);
    //        Serial.readBytes(RecievedTemp1, 20);
    //        //Serial.println(RecievedTemp1[cout_i]);
    //    }
        Serial.readBytes(RecievedTemp1, 20);
    //    for(cout_i = 0; cout_i < 19; cout_i ++)
    //    {
    //    Serial.println(RecievedTemp1[cout_i]);
    //    }
        switch(RecievedTemp1[13])
      {
      case 49:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image2\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang1++;
            quan_lie1++;
            quan_youxia++;
    //        quan[0]++;
    //        quan[3]++;
    //        quan[7]++;
            Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button1\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image2\",\"image\":\"x\"}>ET");
             r_flag1 = 0;
                cha_hang1++;
                cha_lie1++;
                cha_youxia++;
    //        cha[0]++;
    //        cha[3]++;
    //        cha[7]++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button1\",\"enable\":false}>ET");
            }
            
            break;
      case 50:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image3\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang1++;
                quan_lie2++;
    //        quan[0]++;
    //        quan[4]++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button2\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image3\",\"image\":\"x\"}>ET");
             r_flag1 = 0;
             cha_hang1++;
               cha_lie2++;
    //        cha[0]++;
    //        cha[4]++;
               Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button2\",\"enable\":false}>ET");
            }
            break;
      case 51:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image4\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang1++;
                quan_lie3++;
                quan_zuoxia++;
    //        quan[0]++;
    //        quan[5]++;
    //        quan[6]++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button3\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image4\",\"image\":\"x\"}>ET");
             r_flag1 = 0;
             cha_hang1++;
               cha_lie3++;
                cha_zuoxia++;
    //        cha[0]++;
    //        cha[5]++;
    //        cha[6]++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button3\",\"enable\":false}>ET");
            }
            break;
      case 52:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image5\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang2++;
                quan_lie1++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button4\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image5\",\"image\":\"x\"}>ET");
             r_flag1 = 0;
             cha_hang2++;
               cha_lie1++;
               Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button4\",\"enable\":false}>ET");
            }
            break;
      case 53:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image6\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang2++;
                quan_lie2++;
                quan_zuoxia++;
                quan_youxia++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button5\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image6\",\"image\":\"x\"}>ET");
              r_flag1 = 0;
              cha_hang2++;
                cha_lie2++;
                cha_zuoxia++;
                cha_youxia++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button5\",\"enable\":false}>ET");
            }
            break;       
      case 54:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image7\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang2++;
                quan_lie3++;
    //        quan[1]++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button6\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image7\",\"image\":\"x\"}>ET");
             r_flag1 = 0;
             cha_hang2++;
               cha_lie3++;
               Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button6\",\"enable\":false}>ET");
            }
            break;       
      case 55:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image8\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang3++;
                quan_lie1++;
                quan_zuoxia++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button7\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image8\",\"image\":\"x\"}>ET");
             r_flag1 = 0;
             cha_hang3++;
               cha_lie1++;
                cha_zuoxia++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button7\",\"enable\":false}>ET");
            }
            break;       
      case 56:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image9\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang3++;
                quan_lie2++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button8\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image9\",\"image\":\"x\"}>ET");
             r_flag1 = 0;
             cha_hang3++;
               cha_lie2++;
               Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button8\",\"enable\":false}>ET");
            }
            break;       
      case 57:
            if((r_flag1 == 0)&&(RecievedTemp1[14]==2))
            {
            Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image10\",\"image\":\"circle\"}>ET");
            r_flag1 = 1;
            quan_hang3++;
                quan_lie3++;
                quan_youxia++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button9\",\"enable\":false}>ET");
            }
            else if((r_flag1 == 1)&&(RecievedTemp1[14]==2))
            {
              Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image10\",\"image\":\"x\"}>ET");
             r_flag1 = 0;
             quan_hang3++;
               quan_lie3++;
                quan_youxia++;
                Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button9\",\"enable\":false}>ET");
            }
            break;
      }
      if((quan_hang1==3)||(cha_hang1==3))
          {
                Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif4\",\"visible\":true}>ET");
          }
          else if((quan_hang2==3)||(cha_hang2==3))
          {
                Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif5\",\"visible\":true}>ET");
          }
          else if((quan_hang3==3)||(cha_hang3==3))
          {
                Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif6\",\"visible\":true}>ET");
          }
          else if((quan_lie1==3)||(cha_lie1==3))
          {
                Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif7\",\"visible\":true}>ET");
          }
          else if((quan_lie2==3)||(cha_lie2==3))
          {
                Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif8\",\"visible\":true}>ET");
          }
          else if((quan_lie3==3)||(cha_lie3==3))
          {
                Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif9\",\"visible\":true}>ET");
          }
          else if((quan_zuoxia==3)||(cha_zuoxia==3))
          {
                Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif10\",\"visible\":true}>ET");
          }
          else if((quan_youxia==3)||(cha_youxia==3))
          {
                Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif11\",\"visible\":true}>ET");
          }
      }
    }
     
  5. bancroft

    bancroft

    47
    1
    Apr 23, 2021
    Thanks for the reply, I was wondering if there was any other way to fix it, except for replacing the board.
    I will also look for a solution on Arduino's website, thanks for the suggestion.
     
  6. Harald Kapp

    Harald Kapp Moderator Moderator

    11,533
    2,656
    Nov 17, 2011
    The error is:
    "Global variables use 3046 Bytes (148 %) of dynamic memory. -998 Bytes remaining for lokal variables " (or similar, I translated the German output from my Arduino IDE).
    My initial assumption was right. You have a total of 42 Serial.Println() statements containing 3495 characters (quick count, give or take a few).
    You have these options:
    1. If these print statements are for debugging only, delete or comment those you do not absolutely need.
    2. If this is not an option, put the print statements into subroutines and call these routines. See below.
    3. Improve the code structure so you don't need a SerialPrintln() statement in every then...else statement but rather set a variable within the statement, then use a single SerialPrintln() at the end of the sequence of if...then...else using this variable. I'm not going to elaborate that as I think it is unlikely you go that way.

    Improving your code:
    You have 42 print statements.
    16 of the type code: set_enable
    18 of the type code: set_image
    8 of the type code: set_visible
    Instead of placing a SerialPrintln() statement in each position, create 3 subroutines acc. to the following scheme:
    Code:
    void Print_Set_Enable(int number)
    {
      Serial.print("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button");
      Serial.print(number);
      Serial.println("\",\"enable\":false}>ET");
    }
    Instead of the Serial.println() calls call this function with the number of the button as an argument like this:
    Code:
    //           Serial.println("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button2\",\"enable\":false}>ET");
               Print_Set_Enable(2);
    Doing this for the above type of print statement alone reduces the data size to 2390 Bytes (116 %), still a bit too much but a noticeable improvement.
    For statements with more than 1 variable content you need accordingliy multiple variables:
    Code:
    Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image2\",\"image\":\"circle\"}>ET");
    Here you have image number (1) and image type ("circle") as variable content to be considered in the function call.
    Do this for the other two types of print statement and you should be god to go. I'll leave it as an exercise to you to fill in the details:
    Code:
    void Print_Set_Enable(int number)
    {
      Serial.print("ST<{\"cmd_code\":\"set_enable\",\"type\":\"widget\",\"widget\":\"button");
      Serial.print(number);
      Serial.println("\",\"enable\":false}>ET");
    }
    
    void Print_Set_Image()
    {
    }
    
    void Print_Set_Visible()
    {
     
    }
    void setup()
    {
       Serial.begin(115200);
       for(int i=3; i<=8; i++)
       pinMode(i,OUTPUT);
    }
    
    void loop(){
    ...
     
  7. Harald Kapp

    Harald Kapp Moderator Moderator

    11,533
    2,656
    Nov 17, 2011
    As a completely different alternative, suitable for cases where you have many different lengthy print statements that do no invite for such a method using subroutines as described above: transfer the burden of storing lots of text to the PC.
    You do this by assigning each event a unique identifier (code), e.g. an unsigned 16 Bit number (good for >65000 codes). Instead of printing a string, you print only a code and have the PC look up the respective long form of the text in a table. Easy to do e.g. within script that reads the output from the serial port and translates it into the text looked up from a table.

    You can also combine the code method with the use of variable where required. Example:
    Instead of 81 characters for this:
    Code:
    Serial.println("ST<{\"cmd_code\":\"set_image\",\"type\":\"image\",\"widget\":\"image2\",\"image\":\"circle\"}>ET");
    You use 6 characters for this:
    Code:
    Serial.println("00AA1c");
    Where
    - 001A would be the code for "ST<{cmd_code:set_image,type:image,widget:'image_number', image:'image_type'}ET"
    - 1 would be the code for image1 -> image_number = 1
    - c would be the code for circle -> image_type = "circle"

    This code snippet in Python shows the principle:
    Code:
    # dummy variable assignment. Put a read from the serial console here
    SerialRead = "001A1c"
    # split into code, arg1 and arg2
    code = SerialRead[0:4]
    arg1 = SerialRead[4:5]
    arg2 = SerialRead[5:6]
    
    if (code == "001A"):
       image_number = "image" + arg1
       if (arg2 == "c"):
          image_type = "circle"
       print("ST<{cmd_code:set_image,type:image,widget:" + image_number + ",image:" + image_type + "}ET")
    Of course this can be solved much more elegantly using e.g. dictionaries. Or maybe you don't have to convert the code to text at all but use it directly to perform some other action on the PC. Also I used Python only as an example. Any other programming language will serve as well. Best one you are familiar with.
     
  8. Harald Kapp

    Harald Kapp Moderator Moderator

    11,533
    2,656
    Nov 17, 2011
    Maybe the most simple solution: use the F-macro. This places the strings into program memory, not data memory. Instead of
    Code:
     Serial.println("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif6\",\"visible\":true}>ET");
    use
    Code:
     Serial.println(F("ST<{\"cmd_code\":\"set_visible\",\"type\":\"widget\",\"widget\":\"gif6\",\"visible\":true}>ET"));
    this reduces the data size to 252 Bytes (12 %).
     
    shumifan50 and bancroft like this.
  9. bancroft

    bancroft

    47
    1
    Apr 23, 2021
    Thank you so much for your enthusiasm and patience in replying, you gave a lot of helpful advice, thank you very much ! I've decided to take the approach you mentioned F-macro to make the changes, and I will update if there are any new developments.
     
    shumifan50 likes this.
  10. DBingaman

    DBingaman

    86
    24
    Jun 27, 2021
    Do you need the range for unsigned int (4 bytes). Can you use throughout your code more unsigned short (2 bytes) or unsigned char (1 byte)?
     
  11. bancroft

    bancroft

    47
    1
    Apr 23, 2021
    Thank you for your reply, I have solved this problem by F().
     
  12. shumifan50

    shumifan50

    576
    57
    Jan 16, 2014
    Be aware that printing to serial has a small buffer and printing large strings will cause loop() to wait while the string is output. This can cause unpredictable results, especially if coms is used.
     
  13. bancroft

    bancroft

    47
    1
    Apr 23, 2021
    I've solved the problem successfully and shared the demo video on youtube, thanks for helping me guys!
     
  14. Harald Kapp

    Harald Kapp Moderator Moderator

    11,533
    2,656
    Nov 17, 2011
    Nice:)
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-