variable historical tracking

Status
Not open for further replies.

oric_dan

Well-known member
I thought I would share this with the group. It's possible someone else already invented the idea, in which case "Never Mind", :). Someone might take a look at the code, and see if I have made any glaring mistakes. I'm using Teensy 3.1 and Windows IDE 1.6.13 here.

I've of course been using print() statements for years for debug. However, this is obviously not the best method, and also generally difficult to get historical tracking data. Recently, I ran across an old article that mentioned storing variable values to a debug queue over time, so I implemented it last night.

Basically, I am using a holding buffer with 1000-cells, and modified the millis() ISR to capture and store variable values for a period of time. Then I can display the history of the variable. I trigger sampling off the first change in value of the variable. In the ISR, I use a divider on the msec count to control how often the variable is sampled. It's kind of like a logic-analyzer in software, and works for variables that don't change super-fast.

Amazingly, it actually worked right off!

Eg, the following printout shows variable NumIRdet, which indicates the #of times a pulse from a 56-KHz IR led was detected (part of an alarm system I am building). The tracker stores a value every 10-msec in this case (for 10-sec total history), and triggers (starts storing) on the first change. The 1st cell in the array shows the variable starting value, and the next cell the 1st change.

So, it gets up to 13 pulse detects after about 240-msec. Then the values after the 1st 3-rows show the variable value decaying back to 0 over time, because I have implemented a "leaky integrator" (elsewhere), which automatically decays the value back to zero (at -20% every second), so I needn't explicitly reset it.

The code is shown below. In the final data dump, I built the IR detect count up over several seconds with 3 different activations of the IR Led spaced a couoe of seconds apart.

I've needed something like this for YEARS. Comments or suggestions???


...Show vHold Array...(10-msec sampling)
0,1,1,1,2,2,2,3,3,4,4,4,5,5,6,6,6,7,7,8,
8,8,9,9,10,10,10,11,11,12,12,12,13,13,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,


Code:
- setup tracking in main program:

   // following is done in main menu routine:
   case 'S':  // setup to track variable during sensor run.
              setup_tracker(&NumIRdet,10);  
              ...(other setup code)...
              break;
   case 'H':  show_vHold();  break;


// earlier declaration.
#define dbg   Serial1


static int vRate=0;    //holds msec divider.

/* Initialize variable tracking.
* inputs: var=address of variable to track.
*         div=msec_divider.
*************************************************/
void setup_tracker( unsigned int *var, int div )
{
  set_vPtr(var,div);
  vRate=div;
}

/*****************************************************/
void show_vHold( void )
{
  dbg.printf("\n...Show vHold Array...(%d-msec sampling)", vRate);


  int num=get_vHoldSize();
  for( int i=0; i<num; i++) {
    if( (i%20) == 0) nl();
    dbg.print( get_vHold(i) );  dbg.write(',');
  }
}


- following code is located in mk20dx128.c, with modified millis() ISR:
  (Note: I saved a backup of the .c file before mucking it up).

/////////////////////////////////////////////
/////  Historical Variable Msec Tracker /////
/////////////////////////////////////////////
// added (12/10/17).

#define NUM_VHLD    1000 
static volatile unsigned int vHold[NUM_VHLD]; //holds variable history.
static volatile unsigned int *vPtr=NULL;      //ptr to variable to store.
static volatile          int vNdx=0;          //index into history.
static volatile          int vCntr=0;         //msec divider counter.
static volatile unsigned int vDivide=0;       //msec divider.
static volatile unsigned int vStart=0;        //start value to match.
static volatile unsigned int vFlag=0;         //enable flag.


#if false     //relocated to end of kinetis.h (Teensy 3.1).
// (12/10/17) Function Prototypes.
extern void set_vPtr(unsigned int *var,unsigned int vdiv);
extern unsigned int get_vHold(int ndx);
extern int get_vHoldSize(void);
#endif


/************************************************/
int get_vHoldSize( void )
{
  return( NUM_VHLD );
}

/************************************************/
unsigned int get_vHold( int ndx )
{
  return( vHold[ndx] );
}

/******************************************************/
void set_vPtr( unsigned int *var, unsigned int vdiv )
{
  vPtr=var;       //point to variable for store.
  vStart=*var;    //starting value of variable.
  vDivide=vdiv;   //set msec divider.
  vNdx=1;         //set index to array start+1.
  vCntr=0;        //clear msec divide counter.
  vFlag=1;        //set to start tracking.

  // clear holding array. 
  // NOTE: for() will not compile here ???
  //for( int i=0; i<NUM_VHLD; i++)  vHold[i]=0;
  int i=0; 
  while( i < NUM_VHLD) vHold[i++]=0;
  vHold[0]=vStart;
}


extern volatile uint32_t systick_millis_count;

/* (12/10/17) modified millis() ISR code.
*****************************************************/
void systick_default_isr(void)
{
    systick_millis_count++;

  // historical variable tracker.
  if( vFlag == 1) {
    if( *vPtr != vStart) {     //trigger tracker.
      vFlag=2;                   //start tracking on first change.
      vHold[vNdx++] = *vPtr;  //store new variable value.
    }
  }
  else if( vFlag == 2) {
    if( (++vCntr) >= vDivide) {
      vCntr=0;                                //restart divider.
      vHold[vNdx++] = *vPtr;         //store variable in buffer.
      if( vNdx >= NUM_VHLD) vFlag=0; //stop counting if buffer full.
    }
  }
  else { }    //do nothing.
}

#if false    //original ISR code.
void systick_default_isr(void)
{
    systick_millis_count++;
}
#endif

////////////////////////////////////////////////


...Show vHold Array...(10-msec sampling)
0,1,1,1,2,2,3,3,3,4,4,4,5,5,6,6,6,7,7,8,
8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,5,5,5,5,5,5,5,5,5,
5,5,5,6,6,6,7,7,8,8,8,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,9,9,
10,10,10,11,11,12,12,12,13,13,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 
Update to what I did a couple of days ago.

I am using the Teensy 3.1 in a home security alarm system, which has multiple sensors (IR detectors, PIR, sonar, environmental, &etc), Ethernet to my router, Xively posts and Tweets, and which also posts a local webpage so I can monitor and control the system locally from an Android tablet, etc. It also uses Hope RFM radios for RF connection to remote nodes, such as an alarm in my van. Everything is currently in various stages of development.

I've had some issues with tracking sensor readings, and developed the previous idea regarding capture and display of variables over time, while I am walking around the room with the tablet. Yesterday, I found a very useful online page for HTML reference, and discovered that HTML5 supports "very simple" scripts for displaying data, so it's not difficult at all to draw data graphs on a webpage. It can be easily done using a uC, even a regular Arduino.

- https://www.w3schools.com/tags/ref_canvas.asp
- https://www.w3schools.com/tags/canvas_moveto.asp
- https://www.w3schools.com/tags/canvas_lineto.asp

My program is somewhat long now (92KBytes of code and 24Kbytes of RAM for T3.1), and the original webpage code is modified from code posted by "zoomkat" a couple of years ago over on the Arduino forum.

So, last night I modified the idea from the previous post, and now have it capturing and displaying 2 inter-related variables graphically to my local webpage. All told, there is a trigger sequence of IR Led detects, then PIR sensor detects, and then the sonar is activated. Example of my webpage, still in development:
ami_webpage_111417a.jpg
 
The RFM radio stuff is not shown on the webpage as yet. For the remote nodes, I am currently using the RFM69 radio at 100-mW along with the Moteino-Mega-1284 modules from lowpowerlabs. 100-mW is the xmit power it took to transmit to "inside" the SUV on the other side of the building about 100-feet away. I've since moved the alarm to the van. I've had these radios since before LoRa became popular. More info on the project is here,

https://lowpowerlab.com/forum/projects/suv-alarm-using-moteino-mega-and-more

I recently did purchase a couple of nodes with ESP32 and LoRa, but not had a chance to try them as yet ==> yet another learning curve, :). Hope to get to those in a coupe of months.

https://www.ebay.com/itm/2pcs-TTGO-...bytes-128-Mt-433Mhz-for-arduino-/152738945981

There are also these,

https://www.ebay.com/itm/SX1276-868...ED-Wifi-Bluetooth-IOT-Development-Board/27289

EDIT:
FYI, 10-mW xmit power is generally adequate for RF nodes inside the house, and I was originally using RFM12 radios, but it turned out that's not enough power to reliably communicate to "inside" the metal SUV the other side of the building, so I went to the 100-mW radios. I probably don't really need LoRa for this project, but plan to try it for general learning reasons.
 
Last edited:
Also, I am not controlling the RFM radios directly with the T3.1 here, as the T3.1 already has lots of work to do with ethernet and everything else, and I've wanted to keep the lone T3.1 SPI port available for other purposes. So, I am using dedicated mega-328 modules like the Pro-Mini to control the radios, and buffer the data into the T3.1 serial port. This is mentioned in that thread on the Moteino forum.
 
Status
Not open for further replies.
Back
Top