Tournament Order of Progression - unofficial answer

This was not a mistake. The staff at a competition do not directly control the enabling or disabling of the robots but instead use the tournament manager software. Robots need to be disabled after the autonomous period, if this were not done it would be difficult to limit the time to 15 seconds and allow scoring to take place. The sequence usually is

disable
enable autonomous
disable
enable driver control
disable

If for some reason there is a technical problem the autonomous period may be restarted but this is rare.

EasyC will run the code in the initialize function every time the robot is enabled followed by either the autonomous or operator function as needed. All regular global and static variables are initialized each time as well :frowning: but there is an array of “global data” that can be used to track things that need to be run once, this array is called “GlobalData” and contains 20 long integers.

1 Like

Thanks jpearman, as usual you are a wealth of knowledge!

My question for you: can you give me a sample snippet of code of how to write to one of these variables and how to retrieve from one of them?

Thanks again!

1 Like

To store data into one of these cells of the global data array you would use


 GlobalData(x) = 0;

Then to retrieve it you would do something like it:


if (GlobalData(x)) == 0
   do something...;

You can replace the x with any number between 0 and 19 to store it into different cells of the array (each cell basically being a long variable).

1 Like

Ok, thanks guys,

So my last question is whether or not the global variables will get reset when the robot is completely powered off/disconnected from the field?

I need it to hold the variable while the bot is initialized and enabled and disabled and enabled again but we will need it to go back to null upon a complete power down.

Or I’ll have to come up with another workaround I guess. Thanks!

This is an interesting question with a frustrating answer I’m afraid.

First, perhaps read through this entire thread.

https://vexforum.com/t/advanced-easyc-programming-non-volatile-parameters/22025/1

You will see in the thread that I started by writing my own code to allow non-volatile storage of user settings in the flash memory. By the last post I had discovered that EasyC does in fact have a crude mechanism for storing the contents of the GlobalData array in flash where the array will be reloaded on power on. Now the bad news, out of respect for the EasyC developers I can’t tell you how to do this :frowning: The developers had a reason for hiding the API and I have to leave it to them to choose to expose it again. There are two issues, the first is that repeated erasure of the flash will eventually destroy it, the number of cycles is not that high and they did not implement any mechanisms (as I did with my own code) to remedy this. The second reason is that during a flash erase (which is required before flash can be re-written) real time performance will be lost, that is, it takes approximately 20mS to erase a flash page during which time interrupts and other background operations cannot operate properly. Your best bet (unless you hack the runtime library as I did) is to use jumpers or a potentiometer to store such settings as autonomous routine selection.

Edit:
I wanted to add that since the original thread I ported the code to ROBOTC, it works quite well for its intended use and is a shame I cannot release it for the same reasons as above.

1 Like

This sounds interesting…

Array Elements are accessed with the Brackets ( e.g **** and ] ) not Parentheses. But because the way ‘C’ works, this might be Legal, but not give you the desired results…

You might need to post the main structure of your code ( I would remove the specifics of your Autonomous Module and the Driver Control Module )

1 Like

Ok, I’ve tried accessing this and it appears it too is being reset back to 0 whenever disable the field with the switch after autonomous. Should this be the case? Perhaps I understood you wrong - maybe you explained it in your last post.

The whole reason for us to get an LCD panel was to make autonomous selections… I’d really like to figure a way around this…

Thanks, I did try and go through and change them all to brackets instead but then I get compile errors stating that the GlobalData[0] variable is undeclared.

I don’t get that error with the parenthesis.

Hmm…

The API.H file has:



#define MAX_GLOBAL_DATA 20
#define GlobalData(C) (easyCGlobalData(C))



Your Right!!

So GlobalData© appears to be a Function, rather than an Array… ( Looks like I need to look in the “#include <globaldata.h>” file )

Sorry for the Miss-Information…

[EDIT]

The line “#include <globaldata.h>” in the API.H file pulls in the following:


#ifndef __GLOBAL_DATA_H
#define __GLOBAL_DATA_H

#define MAX_EASYC_GLOBALS 20
extern unsigned long g_ulGlobalData];
#define easyCGlobalData(C) (g_ulGlobalData[C < 1 || C > MAX_EASYC_GLOBALS ? 0 : C])

#endif

So your code snippets should be good… Can you Post your Project, minus any Secret Code???

[/EDIT]

Let me try an example later and post some working code if it is as I remember.

Edit:
Some weird stuff happening, looks like GlobalData is being written to flash despite what I said earlier. I need to figure out if this was a change in 4.1.0.5 or if it in fact existed in earlier versions. It seems to get written if leaving Initialize. Not what I expected at all, however, the last time I looked into this was several months ago.

1 Like

Well, EasyC sure is a mess. Here’s what I have been able to figure out so far.

The GlobalData array is saved to flash when using the competition switch connected to the joystick. This seems to happen when the robot is disabled and a difference detected between what is in the GlobalData array and the flash memory. When the robot is powered on the GlobalData is loaded from flash, the problem here is that if you want to use GlobalData to indicate that code should be run exactly once then this only happens the first time after a new program is downloaded and never on subsequent power cycles. None of this happens if the competition switch is not connected as the robot will never see a disabled condition. I do not like the way GlobalData is being saved to flash, EasyC is doing a page erase each time the robot is disabled and a difference in the data detected, this is putting unneeded stress on that flash page without knowledge of the programmer. I’m not sure what’s going on with Intelitek these days but the lack of updates gives me a feeling they are not putting much resource into EasyC so doubt this will be improved. GlobalData is saved to flash at address 0x0805F800 if anyone is interested.

Anyway, the ideas from below will never work, we need to find a different way.

EasyC has a whole bunch of undocumented functions. One pair it has are ReadUserBit() and WriteUserBit(). These functions seem to be used by the competition control code to save some state information using an unconnected GPIO port (portF). I notice that ReadUserBit() returns 0 when initialize first runs before the robot is enabled and then disabled but returns 1 after that. This would appear to be something we can use to allow some initialization code to run just once. The code below is a work in progress but the idea is something like this.

// external function
unsigned char ReadUserBit(void);
// a global
int  auto_selection;

void Initialize ( void )
{
      unsigned char lcd_l; 
      unsigned char lcd_c; 
      unsigned char lcd_r; 
      int i; 
      int firstrun; 

      InitLCD ( 2 ) ;
      Wait ( 500 ) ;
      SetLCDText ( 2 , 1 , "Initialize" ) ;

      firstrun = ReadUserBit() ;

      if ( firstrun == 0 )
            {
            SetLCDText ( 2 , 1 , "Select" ) ;
            SetLCDText ( 2 , 2 , "%d" , auto_selection ) ;
            StartLCDButtonsWatcher ( 2 ) ;
            while ( !IsEnabled() )
                  {
                  GetLCDButtonsWatcher ( 2 , &lcd_l , &lcd_c , &lcd_r ) ;
                  if ( (lcd_l + lcd_c + lcd_r) > 0 )
                        {
                        if ( lcd_l == 1 )
                            {
                            if ( auto_selection > 0 )
                                auto_selection-- ;
                            else
                                auto_selection = 5 ;
                            }
                        if ( lcd_r == 1 )
                            {
                            if ( auto_selection < 5 )
                                auto_selection++ ;
                            else
                                auto_selection = 0 ;
                            }
                        SetLCDText ( 2 , 2 , "%d" , auto_selection ) ;
                        while ( (lcd_l + lcd_c + lcd_r) != 0 )
                            {
                            GetLCDButtonsWatcher ( 2 , &lcd_l , &lcd_c , &lcd_r ) ;
                            Wait ( 25 ) ;
                            }
                        }
                  Wait ( 25 ) ;
                  }
            
            StopLCDButtonsWatcher ( 2 ) ;
            }
}

Another way would be to abandon the whole idea of only running this code once. It doesn’t really matter if the selection code runs again before driver control, the autonomous has already run so what if that variable gets set back to 0. Anyway, I will give it some more thought, the more I use EasyC the less I like the way the underlying library code is written, there is lots of power there if you bypass their code but it’s not really practical for most students.

1 Like

If a Status Variable or Flag could indicated Autonomous or OperatorControl, then you chose when to Run the Code.

There’s nothing official as far as I can see. In ROBOTC there are flags to do this but they are only valid when the robot is enabled, it’s as if when the robot is disabled it always indicates autonomous mode.

I have another idea for creating some global data that would behave in the way that I thought GlobalData was. When I used GlobalData the last time I did not have the competition switch connected, normally it can not get written to flash under user control, that was the undocumented function I had found.

1 Like

I would suggest the following update…

Using the COMPETITION SWITCH SIMULATOR with EasyC 4.1.0.5, the Initialize function is called at DISABLE, not ENABLE…

The program path looks like:

disable
call Initialize
enable autonomous
call autonomous
disable
call Initialize
enable driver control
call driver control
disable

The real COMPETITION SWITCH might vary in operation…

Code provided in Post #44 of thread, Simple Programming Questions.

Oops!!! I was Wrong… In Rushing the Testing, I was not checking things thoroughly…

WRONG CONCLUSION
I think I have found a potential work around to shared data between Init, Auto and Operator, no flash writes, all in RAM… EasyC 4.x Code Sample posted tomorrow…

It uses local static variables in an Independent function…

RIGHT CONCLUSION
On the DISABLE of the COMPETITION SWITCH SIMULATOR, Everything on the Cortex User Processor seems to be Reset, just like a Power On.

I am posting this Test Code… It might be helpful in the Future with EasyC.

As of EasyC v4.1.0.5, when the COMPETITION SWITCH SIMULATOR is set to DISABLE, a Reset appears to be performed, which Clears all Global Variables, including the ones declared as Static within a Function.
Repository_Concept_000a.zip (7.04 KB)

I know it’s going far back in the thread, but I have an answer from personal experience that addresses the original question as far as GlobalData is concerned and may or may not help you (MarkO) with your experiments.

We have written in EasyC an autonomous selection routine that runs before each match (inside of the initialize function).

It is fairly simple, pressing either the left or right LCD button decrements or increments GlobalData(1). Then, inside of the autonomous function there is a switch/case that runs our routine based upon this number.
In my experiance when hooked to a match controller (in competition), the GlobalData(1) retained its value completely, even when the robot is turned off.
To be clear, if we choose to run our #4 routine, in the next match when we start up our robot again the value is already at 4.

I have not done significant testing with this using a competition switch simulator or the handheld switch.

In competition I follow the following procedures:

  1. With the robot and controller turned off, Connect the joystick to the field.
  2. Turn on the controller.
  3. Turn on the robot.
  4. After the match is over and we are given the all clear to remove our robots
    from the field, remove the cable connecting the controller to the field.
    This causes the initialize function to run again (not sure if this is significant or not) then goes into driver control.
  5. Turn off both the robot and controller.
  6. I do not disconnect the 9V battery as recommended.

If I follow these procedures exactly, I do not need to remove the 9V. However, if I were to turn off the controller then disconnect from the field and turn off the robot, the cortex would remain disabled and the 9V would need to be disconnected and reconnected or else problems will arise at the beginning of the next match.

I’m not sure if these procedures are significant or not, but since they aren’t exactly standard I figured they would help if you were to attempt to replicate my results.

Unless GlobalData retaining its value even when the robot is powered off is an already known fact…:stuck_out_tongue:

1 Like