Counting and Timing a shock sensor

I just realized I hadn’t posted the last working version of the EEPROM utility program, which you’ll need to run to load up EEPROM before the UI code above can work. Alas that’s now on my home PC which is … at home. So I’ll post that code when I get home and then you can try that (to load the EEPROM) and after that, you can try the UI code above.

There are some things about the UI that need some discussion as I’m unsure about the “best” path to take.

First I’ve set up the UI to mimic what I think the timer code should eventually do, that is store the last CoF used and recall those settings whenever it’s powered up or reset. You could have it, instead, return to some default CoF settings but my guess was that the former was more user friendly. Your thoughts ??

I want the user to have some options when exitting the UI with regards to whether to use the new settings or not, and whether to save them to EEPROM or not. I figured there’s going to be a time when you think you want to change some setting, say time allowed, go into the UI to make the change and then change your mind. You need a way to exit the UI w/o making any changes … so the UI has an exit option to just exit. You may also have the idea that you want to try out some change(s) before you save them away … to see if they “work”. So the UI has an exit option to keep the changes made, exit the UI with them in effect but not saved to EEPROM. Conceivably you could try them out and re-enter the UI and then save them to EEPROM. Lastly the UI has the exit option to exit and save the changes to EEPROM into one the prenamed CoF’s. But there’s a “conflict” with the above and the earlier idea that whatever CoF was last used should be saved somehow and restored upon power up/reset. So do we want to “save” the CoF that was in place if the user “exitted w/o saving” ?? I was trying to make some provision for this with a slot in EEPROM called “Last Used” but now I’m not sure that’s the best thing to do (or how to do it). Perhaps an “unsaved” CoF should just be lost upon power off or reset ??

What resolution to you want to have when setting a time limit via the UI ? Right now it’s 1 whole sec, which is too coarse IMO but is 0.5 secs good enough ? 0.1 secs ?? The “conflict” comes when setting the time with the UI; I have the UI increment the time by whatever the resolution is with each “up button” press (or just hold the “button”). The UI polls the analog inputs every .2+ secs to read the button and do whats commanded. So coarse resolution gets you from 5 secs to 50 secs quickly but a 0.1 sec resolution would take 10x longer. Speeding up the polling would help but then you run into the problem that you can’t press and release the “button” fast enough, you always get a double (or triple) press. Now perhaps some adaptive code that reads the joystick as up and really up (so as to make the increment 5x larger) can be implemented … I just haven’t gotten that far. But is it needed ? Let’s decide on a resolution and then fix whatever user interface problem results.

Do you want a nag prompt before overwriting a CoF ? I thought to make some CoFs edit-able and have others locked out (from the UI) but haven’t implemented this part yet. Perhaps they should all be edit-able from the UI with … or with out … a nag prompt (“Are you sure you want to change this”) before saving to EEPROM ??

Here’s the OLED compatible version of the working version of the EEPROM utility program I used to load CoFs into EEPROM (successfully) and verify those contents. It compiles and should work for you as the LCD portions of the code is pretty simplistic. Run this sketch and watch the serial monitor for confirmation that EEPROM was loaded. The LCD should tell you what’s going on as the program runs.

Then you can try the UI.

#include <OLEDFourBit.h>
#include <EEPROM.h>

// initialize the library with the numbers of the interface pins
OLEDFourBit lcd(12, 11, 5, 4, 9, 8);


// declare some constants
const byte wblocksize = 20;
const unsigned long maskHigh = 0xF000;
const unsigned long maskMidU = 0x0F00;
const unsigned long maskMidL = 0x00F0;
const unsigned long maskLow = 0x000F;

//declare some variables
byte magicNumber = 0xAA;
char CoFname[11];
unsigned long StopTime = 0;
byte NumShooters = 0;
byte RanDly = 0;
byte StopHits = 0;
byte EEblocksize = 0;
byte numCoF = 8;

//here's all the CoF parameters put into various arrays
char* CoFlist[] = {"Last Used ","Standard 1","QuickDraw2","    21    "," Custom 1 ",
" Custom 2 "," Custom 3 ","  A vs B  "};
byte aNumShooters[] = {1, 1, 2, 1, 1, 2, 1, 2};
byte aRanDly[] = {1, 1, 1, 1, 1, 1, 1, 1};
byte aStopHits[] = {6, 24, 1, 20, 20, 20, 12, 20};
unsigned long aStopTime[] = {10001, 20001, 10001, 1501, 20001, 20001, 30001, 24001};


void setup()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("  EEPROM  Utility   ");
  lcd.setCursor(0, 1);
  lcd.print("   Program v0.1     ");
  delay(3000);

  // opens serial port, sets data rate to 9600 bps
  Serial.begin(9600);
  
  lcd.setCursor(0, 1);
  lcd.print(" -writing to EEPROM ");
  delay(1000);
  
  //Write all the CoF parameters to EEPROM
  for (byte i = 0; i < numCoF; i++)
  {
    CoFname[0] = CoFlist[i][0];
    CoFname[1] = CoFlist[i][1];
    CoFname[2] = CoFlist[i][2];
    CoFname[3] = CoFlist[i][3];
    CoFname[4] = CoFlist[i][4];
    CoFname[5] = CoFlist[i][5];
    CoFname[6] = CoFlist[i][6];
    CoFname[7] = CoFlist[i][7];
    CoFname[8] = CoFlist[i][8];
    CoFname[9] = CoFlist[i][9];
    CoFname[10] = CoFlist[i][10];
    
    NumShooters = aNumShooters[i];
    RanDly = aRanDly[i];
    StopHits = aStopHits[i];
    StopTime = aStopTime[i];
    Serial.print("CoF Name #");
    Serial.print(i+1);
    Serial.print(" is : ");
    Serial.println(CoFname);
    Serial.println("Write values are :");
    Serial.print("# Shooters is : ");
    Serial.println(NumShooters);
    Serial.print("Random/Fixed delay is : ");
    Serial.println(RanDly);
    Serial.print("Stop hits # is : ");
    Serial.println(StopHits);
    Serial.print("Stop time is : ");
    Serial.println(StopTime);
    Serial.println(' ');
    save_CoF(i);
  }

  lcd.setCursor(0, 1);
  lcd.print("-reading block size ");
  delay(1000);
  
  // now check what was written to EEPROM
  
  // Map out EEPROM for block size and number of CoFs
  // Read the first EEPROM location and verify it's one of the magic numbers
  if (EEPROM.read(0) == 0xAA)
  {
    // Read each subsequent byte of EEPROM to find next that has a magic number in it
    byte i = 0;
    do
    {
      i++;
    } while (EEPROM.read(i) != 0xAA);
    EEblocksize = i;
    // Using EEblocksize find how many CoFs are stored
    i = 0;
    do
    {
      i++;
    } while (EEPROM.read(i * EEblocksize) == 0xAA);
    numCoF = i;
  }
  else
  {
    Serial.print("Error, can't find magic number");
  }
  
    lcd.setCursor(0, 1);
    lcd.print(" -getting CoF data  ");
    delay(1000);
    //Now retrieve and print each CoF from EEPROM
  for (int i = 0; i < numCoF; i++)
  {
    get_CoF(i);
    // Send this data to the serial monitor
    Serial.println("   ");
    Serial.println("Values read from EEPROM are :");
    Serial.print("CoF Name #");
    Serial.print(i+1);
    Serial.print(" is : ");
    Serial.println(CoFname);
    Serial.print("# Shooters is : ");
    Serial.println(NumShooters);
    Serial.print("Random/Fixed delay is : ");
    Serial.println(RanDly);
    Serial.print("Stop hits # is : ");
    Serial.println(StopHits);
    Serial.print("Stop time is : ");
    Serial.println(StopTime);
  }
}
void loop()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("      All Done      ");
  lcd.setCursor(0, 1);
  lcd.print(" -verify printouts  ");
  delay(5000);
  delay(5000);
  Serial.println("All done ");
  delay(5000);
  delay(5000);
}

// function to recall a CoF from EEPROM
void get_CoF(byte indx)
{
  int base = indx * EEblocksize;
  magicNumber = EEPROM.read(base);
  if (magicNumber == 0xAA)
  {
    for (int i = 0; i < sizeof(CoFname); i++)
    {
      CoFname[i] = EEPROM.read(base + 1 + i);
    }
    NumShooters = EEPROM.read(base + sizeof(CoFname) + 2);
    RanDly = EEPROM.read(base + sizeof(CoFname) + 3);
    StopHits = EEPROM.read(base + sizeof(CoFname) + 4);
    unsigned long temp = EEPROM.read(base + sizeof(CoFname) + 5) << 12;
    temp |= EEPROM.read(base + sizeof(CoFname) + 6) << 8;
    temp |= EEPROM.read(base + sizeof(CoFname) + 7) << 4;
    StopTime = temp | EEPROM.read(base + sizeof(CoFname) + 8);
  }
  else
  {
    Serial.print("Error, can't get magic number from EEPROM");
  }
}


// function to save a CoF to EEPROM
void save_CoF(byte indx)
{
  int base = indx * wblocksize;
  EEPROM.write(base, magicNumber);
  for (int i = 0; i < sizeof(CoFname); i++)
  {
    EEPROM.write(base + 1 + i, CoFname[i]);
  }
  EEPROM.write(base + sizeof(CoFname) + 2, NumShooters);
  EEPROM.write(base + sizeof(CoFname) + 3, RanDly);
  EEPROM.write(base + sizeof(CoFname) + 4, StopHits);
  byte temp = byte((StopTime & maskHigh) >> 12);
  EEPROM.write(base + sizeof(CoFname) + 5, temp);
  temp = byte((StopTime & maskMidU) >> 8);
  EEPROM.write(base + sizeof(CoFname) + 6, temp);
  temp = byte((StopTime & maskMidL) >> 4);
  EEPROM.write(base + sizeof(CoFname) + 7, temp);
  temp = byte(StopTime & maskLow);
  EEPROM.write(base + sizeof(CoFname) + 8, temp);
}

Can’t get the UI to work.

It loads up fine but my joystick of awesomeness won’t move it.

I loaded up a sketch to see what the thresholds should be and modified the values so they should work for both axes and still nothing.

Video of the EEPROM sketch.

http://www.youtube.com/watch?v=5BRci2Zz … e=youtu.be

sspbass:
Can’t get the UI to work.

It loads up fine but my joystick of awesomeness won’t move it.

I loaded up a sketch to see what the thresholds should be and modified the values so they should work for both axes and still nothing.

Looks like EEPROM was loaded successfully !

As for UI and slidey pot … I take it you had/have a test sketch that just prints out A0 and A1 readings to the serial monitor? What were the max and min values when you pushed the joystick to it’s limits ? And what were some typical “on center” or “return to center” values ? I’ve heard there’s a wide variance in where these joysticks go when left to return to center on their own. I’m curious as to whether a 2 stage scrolling (fast and faster based on A0/A1 reading) can be made to work reliably with the joystick of awesomeness.

I assume the code compiled and ran, in non-UI mode (UI mode = 0 on serial monitor), just fine ? When you say “won’t move it” do you mean you couldn’t get into UI mode or that you did get into UI mode (UI mode = 1 on serial monitor) and that navigation from menu to menu didn’t work. That is you were stuck on the “Select CoF” screen … and even then couldn’t select the CoF ?

Did you add a new switch to pin 6 (digital input 6) and hold it closed (supply a ground to Arduino) for 1+ secs to get into UI mode ? My guess is this is where the problem lies. In case I wasn’t clear, the “select switch” is new. You need to have left and right hit detectors/switches, a start/stop switch and a select switch … plus the J.of.A. Holding the new select switch down for 1+ secs (but not too much longer) will get you into UI mode. J.of.A will navigate through the various menus (left/right) and change selections/numbers (up/down). The select switch is used in UI mode to verify the selection a CoF to be loaded from EEPROM and to choose which exit option to use (to get out of UI mode).

The reasoning behind using another switch for the “select” function (vs reusing the start/stop) was that when the timer is not running and you want to enter the UI mode to change some setting or select a new CoF, double-use of the start button would trigger the timer to start the count down. Sure holding the button for 1 sec would probably stop the timer before the shortest countdown time could elapse … but that seemed bush league. Another pin was free so why not use it. Plus you need another button/switch when in UI mode to select/verify some things, after using the J.of.A to navigate to them.

If you did add another switch btw pin6 and ground and held it closed for 1+ sec and still didn’t get into UI mode … that’s odd. In this case post the UI code you used (with new threshold values) and let me make sure something didn’t get lost in going from my PC to the forum to your PC. You may want to check, with a voltmeter, that a good ground is supplied to pin 6 when the switch is closed … and that it’s 5V when not pressed.

Forgot about pin 6. I did have a button hooked up but forgot to do the long hold.

It’s working!

I don’t have time to post a vid as I’m headed to work shortly/

I’m also camping this weekend so I’m not sure i I’ll have time to upload one before I leave or not.

This is just the UI though correct? I can change all the settings and get back to the correct screen but I can’t actually run the COF.

sspbass:
This is just the UI though correct? I can change all the settings and get back to the correct screen but I can’t actually run the COF.

Correct. This code is just a UI playground. I wanted to be able to debug any UI issues w/o the complication of the rest of the timer code. You should be able to recall CoFs from EEPROM, alter any setting desired and save (or not, as you please) the revised CoF to EEPROM (and recall that now modified CoF later). If I get a chance btw the MaiTai’s this weekend I may combine the UI with the timer to get a 1’st cut at the real deal ! I’ll just have to figure out how to handle the “last used” issue raised a few posts ago …

I’m not supposed to be doing something am I?

sspbass:
I’m not supposed to be doing something am I?

I'm sure the wife/GF has the answer for that ! :mrgreen:

I’ve been busy at work doing … work. {gack} I have figured out (I think) the “best” way to handle the UI and what and how to store away the CoF info. I’ve partially re-written the EEPROM utility program, as the new setup will use EEPROM to store more info than just the CoF parameters. So sometime this week I should have a new, combined UI + timer base to fool with.

Just an update … I’ve not forgotten this project, just been busy. Between MaiTais this weekend I intend to finish integrating the new EEPROM storage concept and the real timer functionality. I’ll be bringing my test setup to the lake cabin to see if it works. A MaiTai if it works, 2 if it doesn’t !

Haha, sounds good.

I’m working on building my garage now so my time is pretty well accounted for anyhow.

Have fun man.