Counting and Timing a shock sensor

sspbass:
I like it but the order seems a bit odd.

Shouldn’t the Save menu be last in the sequence?

Also, shouldn’t the number of hits and the time out menus be after the CoF is selected as well as only displaying the one that is needed.

i.e. if I’m setting the number of hits I want to time to there’s no need to select the time out time, it should just be set to the max.

When you get into that series of menus, you first land on the Select CoF : menu. From there you can go either right or left after choosing (or not !) a CoF.

Left would get you to the Save Options : menu, which will allow you to exit after choosing the CoF. Exit and use would be the first choice, presumably the most used after selecting a CoF and not modifying anything about it.

Right will get you to the Select # of shooters :, which I thought might be the most usually changed preset from a presaved CoF.

Going right from there will get you to the countdown delay menu.

Going right again will then get you to the stop hits menu.

Going right yet again will then get you to the stop time menu.

Going right once more will then get you to the Save Options : menu, where you can elect to save all the presets you’ve just changed. So it’s last after going through all the things you might want to change.

But since it’s all a big ring, you can opt to go left, left, left to get to the menu item you want to change the preset you want to change. Or left, left, right …

Of course the order of the displays/menus can be changed, it all depends on which items you think will be most used and therefore should be closer to the “home” menu you land on when you first get into this UI. My thinking was you’d have timed CoFs or hit limited CoFs already setup, so choosing one of those from a list would be the most common. Thereafter it would be either :

  • altering the # of shooters, as a friend may want to join in the fray or

  • just exitting the menus to use the CoF selected.

So these were placed 1 button push away from the “home” menu. The order of the others was my best guess at some late AM hour. :mrgreen:

Ok gotcha, makes sense now.

Heres the latest sketch, unfortunately it’s a little messed up.

http://www.youtube.com/my_videos_upload

You might want to check that link.

New one.

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

I see 2 problems; the offset for the hits in the running display doesn’t change when hits number > 9. It should but there was an extra ; where there shouldn’t have been so removing that might fix that issue.

Also the spacing is AFU in the review display once the hits do get into double digits. I see the cause for that problem and I have a fix for it below. In fact I hope the below is even more puuurty in that it shouldn’t print out any extra A’s or :'s or numbers if there’s no hit data to go with it (at least in the single shooter cases)

void UpdateLCD()
{
AupDtFlag = 0;
BupDtFlag = 0;
// routine to format lines of data to be sent to LCD
// presently assume 4 lines of 20 characters
// formatting based number of shooters and timer state
  if(TimerState)
  {
  // timer is running
    // display number of hits so far
    lcd.clear();
    lcd.print(" A: # hits = ");
    if(A_count < 10)
    {
      lcd.print(' ');
    } 
    lcd.print(A_count);
    // now display the time of last hit
    lcd.setCursor(0, 1);
    lcd.print(" Hit  time = ");
    if(A_count)
    {
      TimeConvert(A_Times[A_count-1]); // convert hit time to XX.xx format
    }
    lcd.setCursor(0, 2);
    // Chose 1 or 2 shooter portion of display
    if(NumShooters == 1)
    {
      // this is for single A shooter running display
      // display the split time btw last hit and prior hit
      unsigned int Split = 0;
      if (A_count > 1)
      {
        Split = A_Times[A_count-1] - A_Times[A_count-2];
      }
      lcd.print("Split time = ");
      TimeConvert(Split); // convert split time
      lcd.setCursor(0, 3);
      // compute A hit factor
      float HF = A_count/A_Times[A_count - 1];
      lcd.print("Hit factor = ");
      char buf[6];
      PString(buf, sizeof(buffer), HF);  // convert FP to char
      lcd.print(buf);
    }      
    else
    {
      // this is for 2 shooter running display
      lcd.print(" B: # hits = ");
      if(B_count < 10)
      {
        lcd.print(' ');
      } 
      lcd.print(B_count);
      lcd.setCursor(0, 3);
      lcd.print("B Hit time = ");
      if(B_count)
      {
        TimeConvert(B_Times[B_count-1]); // Now for B times
      }    
  }
  else
  {
  // timer is stopped
    if(NumShooters == 1)
    {
      // this is single shooter review display
      lcd.clear();
      byte k = 0;                    // k will hold LCD line number
      byte j = DisplayIndex << 3;    // index for first hit time displayed
      byte jj = (A_count % 8);   // jj holds number hits on last display
      if (DisplayIndex == diMax)     // diMax indicates last screen of hits
      {
        jj = j + min(jj,4);          // limit lines according to number of hits
      }
      else
      {
        jj = j + 4;                  // there are enough hits to fill 4 lines
      }
      for (byte i = j; i < jj; i++)
      {
        k = (i % 4);
        lcd.setCursor(0,k);
        lcd.print('A');
        if(i<9)
        {
         lcd.print(' ');             // add a space for single digit numbers
        }
        lcd.print(i+1);              // send hit # to LCD
        lcd.print(": ");
        TimeConvert(A_Times[i]);     // convert hit time to XX.xx format
        if(A_Times[i+4])             // if there's a non-zero time
        {
          lcd.print(' ');            // print a space
          if((i+4)<9)
          {
           lcd.print(' ');           // add a space for single digit numbers
          }          
          lcd.print(i+5);            // send hit # to LCD
          lcd.print(": ");
          TimeConvert(A_Times[i+4]); // convert hit time to XX.xx format
        }
      }
    }      
    else
    {
      // this is 2 shooter review display
      lcd.clear();
      byte k = 0;                     // k will hold LCD line number
      byte j = DisplayIndex << 2;        // index for first hit time displayed
      byte jj = max(A_count,B_count); // init jj to max hit count
      if (DisplayIndex == diMax)      // diMax indicates last screen of hits
      {
        jj = j + (jj % 4);            // limit lines per number of hits
      }
      else
      {
        jj = j + 4;                   // there are enough hits to fill 4 lines
      }
      for (byte i = j; i < jj; i++)
      {
        k = (i % 4);
        lcd.setCursor(0,k);
        if(i<9)
        {
          lcd.print(' ')              // for hits 1-9 put in a leading space
        }
        lcd.print(i+1);               // print hit number
        lcd.print(" A: ");
        TimeConvert(A_Times[i]);      // convert hit time to XX.xx format
        if(B_Times[i]);
        {
          lcd.print(" B: ");
          TimeConvert(B_Times[i]);      // convert hit time to XX.xx format
        }
      }  
    }
  }
}

I tried to add the hit factor for the 1 shooter running display. If that screws up in any way, comment it out.

I take it the timer ran just fine, that is was only the display that was AFU ?

Ok, I’ll try your new code in a few minutes. I think I got everything together I’m going to order for this project. Look over the list and let me know what you think.

  1. Newhaven 4x20 green on black OLED display

  2. Components for another hit sensor. (caps, multivibrator, protoboard, Female Ethernet connector for CAT5 cable, Altoids can for sensor case)

  3. 16 MHz crystal, 20pF caps, 28 pin socket, ATMEGA328 with Arduino bootloader pre-loaded. (For when I move to a more permanent board)

  4. Thumb Slide Joystick (PSP analog joystick)

  5. Hakko FX-888 Soldering Iron (I don’t currently have one)

I was thinking I would also need a ribbon cable for the display when it gets installed into an enclosure but I’m having difficulty finding one.

Is there something I’m not understanding?

I found a problem and fixed it in the above. The snippet fixed is :

      if (DisplayIndex == diMax)     // diMax indicates last screen of hits
      {
        jj = j + min(jj,4);          // limit lines according to number of hits

It used to be a max() instead of the (correct) min().

if (A_count > 1)
      {
        Split = A_Times[A_count-1] - A_Times[A_count-2];
      }
      lcd.print("Split time = ");
      TimeConvert(Split); // convert split time
      lcd.setCursor(0, 3);
      // compute A hit factor
      float HF = A_count/A_Times[A_count - 1];
      lcd.print("Hit factor = ");
      char buf[6];
      PString(buf, sizeof(buffer), HF);  // convert FP to char
      lcd.print(buf);
    }

buffer wasn’t declared. What is it supposed to be set to?

sspbass:
Ok, I’ll try your new code in a few minutes. I think I got everything together I’m going to order for this project. Look over the list and let me know what you think.

  1. Newhaven 4x20 green on black OLED display

  2. Components for another hit sensor. (caps, multivibrator, protoboard, Female Ethernet connector for CAT5 cable, Altoids can for sensor case)

  3. 16 MHz crystal, 20pF caps, 28 pin socket, ATMEGA328 with Arduino bootloader pre-loaded. (For when I move to a more permanent board)

  4. Thumb Slide Joystick (PSP analog joystick)

  5. Hakko FX-888 Soldering Iron (I don’t currently have one)

I was thinking I would also need a ribbon cable for the display when it gets installed into an enclosure but I’m having difficulty finding one.

Is there something I’m not understanding?

WRT to the x-tal and other stuff … what’s your thinking re: the final product design ? Are you going to have a custom PCB laid out ? Or do it yourself ?? For a 1-off project this might be more $$s and trouble than it’s worth. Have you looked into getting a stripped down “Arduino” ? One of the “pro” versions SFE sells or a [RBBB version ?

Get some more micro switches, just like the ones you have so you have spares to test with. I’d also ask you if you want 2 start/stop buttons ? If you ever get the timer belt mounted you might find it nice to have one on the “front” and one on the “top”. If you don’t have some assortment of resistors, you might want to get some 1Ks, 2.2Ks, 5Ks and 10Ks. Maybe an LED or 2. I’m thinking a green LED that shows that the timer is running or stopped, mounted on the case, might be nice. You might want to think about a R/G LED.

I can’t say much about the iron. I have an old Weller I use less and less given most stuff is SMD these days. I’m going to have to learn to use a toaster oven like everyone else one of these days. :mrgreen:

As for connectorizing the LCD … I dunno. I’ll have to look into it. Even if you have to split the ends to solder to the LCD, the other end could be connectorized to the standard 0.1" to allow easy assy to whatever PCB you end up with.

EDIT : I see the LCD has solder tabs spaced 2.54 mm (0.1") so something like the following would be soldered to it and then a ribbon cable with a female IDC type connector (probably use the same at both ends) would be plugged into that header.

http://www.sparkfun.com/products/117

http://www.sparkfun.com/products/10646

You can also right angle and female versions if you want.](http://shop.moderndevice.com/products/rbbb-kit)

sspbass:
buffer wasn’t declared. What is it supposed to be set to?

Hmmm, the char buf[6]; is that declaration. What am I missing ? OOOOOOPPPPPS, that “buffer” is supposed to be “buf”.

if (A_count > 1)
      {
        Split = A_Times[A_count-1] - A_Times[A_count-2];
      }
      lcd.print("Split time = ");
      TimeConvert(Split); // convert split time
      lcd.setCursor(0, 3);
      // compute A hit factor
      float HF = A_count/A_Times[A_count - 1];
      lcd.print("Hit factor = ");
      char buf[6];
      PString(buf, sizeof(buf), HF);  // convert FP to char
      lcd.print(buf);
    }

Have I said how much I hate coding ?

You may hate coding, but I hate debugging at the hardware level. At least with my code on a regular machine I can trace the flow of execution. When working with real hardware that you can’t step through code on, this induces some serious headaches. Of course if I had some more tools (o-scope and a logic probe would be nice), it would make it easier.

But I came to comment more on the next phase. I don’t think it would be too bad to go through someone like Dorkbot or BatchPCB to get some initial boards made up. Once I have my code and hardware nearly finalized I plan to purchased about 5 boards and fully wire them up and place them into test hulls. Right now it is all protoboard (Mee_n_Mac has seen the work in another thread). I can’t wait to shrink this onto a PCB and hand it to my boys to field test it. Hopefully it won’t break in the first 10 minutes, but that could happen.

Before you design your PCB though I would make sure you know the enclosure you are going to use. Going with a fully custom fabbed enclosure is expensive. I am planning on finding a small box that I can mount into a vacuum formed shell. This way I can hopefully mount and unmount between different models while testing. Once I find the right box I will make sure that my PCB fits. Ideally it would be nice if I could make it water resistant, but this can wait.

Good luck, sounds like you are making it quite far into your prototyping stage, I always love to see the finished project.

Dan

And now for something completely different …

Here’s a 1’st cut at making some form of User Interface. It doesn’t do much other than let you know which button you pushed (via the serial monitor) and display the UI shown some posts ago. You can navigate from menu to menu and change things but they don’t do anything. In fact there’s no timer function at all, just the base UI. ATM you’ll need 4 buttons/switches to navigate. These should be wired just like you’ve done for the start and scroll buttons, one side to ground and the other to the pin number below. The code applies an internal pull-up. There should already be the start and scroll buttons on pins 7 and 6. Adding another pair (if you have them) of N.O. switches across pins 2 and 3 won’t affect the timer operation, so long as you don’t push them with the timer code loaded and running. So the wiring setup for this sketch can coincide with the timer sketch.

Up Button = pin 2

Down Button = pin 3

Left Button = pin 6

Right Button = pin 7

#include <LiquidCrystal.h>

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

// set pin numbers
const byte UpPin = 2;           // the Up button pin
const byte DownPin = 3;         // the down button pin
const byte LeftPin = 6;         // the left button pin
const byte RightPin = 7;        // the right button pin
const byte LEDPin = 13;         // the number of the LED output pin

// initialize the constants
const unsigned long DB_delay = 300;      // set a debounce wait time of 300 msecs
const int MaxTime = 30;                  // the max time the timer can run for = 30 secs
const byte MaxHits = 24;                 // Maximum number if hits allowed

const char* MenuList[0] ="    Select CoF:     "
const char* MenuList[1] =" Select # shooters: "
const char* MenuList[2] ="   Select Delay:    "
const char* MenuList[3] =" Select # of hits:  "
const char* MenuList[4] =" Select stop time : "
const char* MenuList[5] ="   Save options:    "

const char* CoFlist[0] = "Standard 1"
const char* CoFlist[1] = "QuickDraw1"
const char* CoFlist[2] = "    21    "
const char* CoFlist[3] = " Custom 1 "
const char* CoFlist[4] = " Custom 2 "
const char* CoFlist[5] = " Custom 3 "
const char* CoFlist[6] = "  A vs B  "

// initialize global variables
byte StopHits = MaxHits;                 // Number if hits allowed before stopping
int StopTime = MaxTime;                  // Time that the timer will stop at 
byte CoF = 0;                            // initialize the mode to be standard
byte NumShooters = 1;                    // initialize the number of shooters to 1
byte Random = 0;

int tmpCoF = Cof;
int tmpRandom = Random;
byte tmpNumShooters = NumShooters;
int tmpStopHits = StopHits;
int tmpStopTime = StopTime;
 
int 4Way[] = {0, 0, 0, 0};
int ptrMenu = 0;
int ptrCoF = 0;
byte numCoF = 7;  // # of CoFs, 7 for now

char Line3[21];


void setup()
{
  // set up the LCD's number of columns and rows 
  lcd.begin(20, 4);
  lcd.clear();
  lcd.print("   User Interface   ");
  lcd.setCursor(0, 1);
  lcd.print("    Initializing    ");
  delay(3000);

  // initialize output pins
  pinMode(LEDPin, OUTPUT);
  digitalWrite(LEDPin, LOW);
   
  // initialize the input pins with internal pullups
  pinMode(UpPin, INPUT);
  pinMode(DownPin, INPUT);
  pinMode(LeftPin, INPUT);
  pinMode(RightPin, INPUT);
  digitalWrite(UpPin, HIGH);   
  digitalWrite(DownPin, HIGH);
  digitalWrite(LeftPin, HIGH);
  digitalWrite(RightPin, HIGH);

  // opens serial port, sets data rate to 9600 bps
  Serial.begin(9600);

  lcd.setCursor(0, 1);
  lcd.print("      Ready       ");
}


void loop()
{
  // read the 4 buttons and set 4Way(LRUD)
  GetButtons()
  
  // set menu to determine which menu item is displayed
  if(4Way[1])    // right button pressed
  {
    ptrMenu++;
  }
  if(4Way[0])    // left button pressed
  {
    ptrMenu--;
  }
  if(ptrMenu<0)  // wrap around
  {
    ptrMenu=5;   // presently 6 menu items 0-5
  }
  if(ptrMenu>5)  // wrap around
  {
    ptrMenu=0;
  }
  
  switch (ptrMenu)  // display menu item set via pointer
  {
    case 0:  // CoF menu
      if(4Way[2])
      {
        ptrCoF++;
      }
      if(4Way[3])
      {
        ptrCoF--;
      }
      if(ptrCoF<1)
      {
        ptrCoF=numCoF;
      }
      if(ptrCoF>numCoF)
      {
        ptrCoF=0;
      Line3 = CoFlist[ptrCof];
      break;
    case 1: // number of shooters menu
      if(4Way[2])
      {
        tmpNumShooters++;
      }
      if(4Way[3])
      {
        tmpNumShooters--;
      }
      if(tmpNumShooters<1)
      {
        tmpNumShooters=2;
      }
      if(tmpNumShooters>2)
      {
        tmpNumShooters=1;
      }
      char buf[21];
      PString(buf, sizeof(buf), tmpNumShooters);  // convert to char
      Line3 = buf;
      break;
    case 2: // countdown delay menu
      if(4Way[2])
      {
        tmpRandom++;
      }
      if(4Way[3])
      {
        tmpRandom--;
      }
      if(tmpRandom<0)
      {
        tmpRandom=1;
      }
      if(tmpRandom>1)
      {
        tmpRandom=0;
      }
      char buf[21];
      PString(buf, sizeof(buf), tmpRandom);  // convert to char
      Line3 = buf;
      break;
    case 3: // Stop hits menu
      if(4Way[2])
      {
        tmpStopHits++;
      }
      if(4Way[3])
      {
        tmpStopHits--;
      }
      if(tmpStopHits<0)
      {
        tmpStopHits=MaxHits;
      }
      if(tmpStopHits>MaxHits)
      {
        tmpStopHits=0;
      }
      char buf[21];
      PString(buf, sizeof(buf), tmpStopHits);  // convert to char
      Line3 = buf;
      break;
    case 4: // Stop time menu
      if(4Way[2])
      {
        tmpStopTime++;
      }
      if(4Way[3])
      {
        tmpStopTime--;
      }
      if(tmpStopTime<0)
      {
        tmpStopTime=MaxTime;
      }
      if(tmpStopTime>MaxTime)
      {
        tmpStopTime=0;
      }
      char buf[21];
      PString(buf, sizeof(buf), tmpStopTime);  // convert to char
      Line3 = buf;
      break;
    case 5: // Save options menu
      Line3 = " Sorry not working  ";
      break;
    default: // error
      Line3 = "       Error        ";
  }

  if(4Way[])                          // if any button pushed
  {
    lcd.clear();
    lcd.setCursor(0,0);               // go to line 1
    lcd.print(MenuList[ptrMenu]);     // Show the Menu
    lcd.setCursor(0,2);               // go to line 3
    lcd.print(Line3);                 // show what Menu item
  }
}

void GetButtons()
{
  // this version will read input pins instead of analogs
  4Way[] = {0, 0, 0, 0};
  digitalWrite(LEDPin, LOW);
  if(LeftPin == 0)
  {
    4Way[0] = 1;
    Serial.println("Left button pushed"); 
  }
  if(RightPin == 0)
  {
    4Way[1] = 1;
    Serial.println("Right button pushed");
  }
  if(UpPin == 0)
  {
    4Way[2] = 1;
    Serial.println("Up button pushed");
  }
  if(DownPin == 0)
  {
    4Way[3] = 1;
    Serial.println("Down button pushed");
  }
  if(4Way[])   // if button pushed debounce it by waiting
  {
    digitalWrite(LEDPin, HIGH);  // turn on LED
    delay(DB_delay);
  }
}

Assuming the above compiles and runs and displays something close to the desired, there’s still a lot of work to do to get the UI to alter and store the values they will control. But you’ve got to start somewhere.

EDIT : I assume you’ve not yet had a chance to D/L or try the above. That’s good as it was not quite right. I’ve fixed the obvious error and put a new version in above. Now it’ll just have un-obvious errors (no doubt pertaining to my misuse of char arrays.

I will be interested if your character arrays works. Something feels wrong about the declaration but I can’t quite put my finger on it. Also, your use of const is probably not what you think it is. You are declaring a pointer constant, not the memory it is pointing at as constant. You probably want something like (and this REALLY feels wrong to me, it just doesn’t look right but I can’t lay my finger on it):

const char * const MenuList[0] = " some string";

I think you need to do something like the following (don’t have a compiler handy to verify this):

char * MenuList[6];
MenuList[0] = "some string";

Hope that helps out.

Dan

dkulinski:
I will be interested if your character arrays works.

Me too !!! :o

dkulinski:
Something feels wrong about the declaration but I can’t quite put my finger on it.

It probably is wrong. I was trying a shortcut given the way you can initialize and declare just an array of characters. If it doesn't work, I think your method looks good. It tells the compiler there's an array of char arrays and then "here they are".

But if neither works out then the following has ( :? ) to work, according to the example here:

http://arduino.cc/en/Reference/String

Arrays of strings
It is often convenient, when working with large amounts of text, such as a project with an LCD display, to setup an array of strings. Because strings themselves are arrays, this is in actually an example of a two-dimensional array.
In the code below, the asterisk after the datatype char “char*” indicates that this is an array of “pointers”. All array names are actually pointers, so this is required to make an array of arrays. Pointers are one of the more esoteric parts of C for beginners to understand, but it isn’t necessary to understand pointers in detail to use them effectively here.
Example
char* myStrings[]={“This is string 1”, “This is string 2”, “This is string 3”,
“This is string 4”, “This is string 5”,“This is string 6”};

So when all else fails remove (or comment them out as I have below) these parts:

//const char* MenuList[0] ="    Select CoF:     "
//const char* MenuList[1] =" Select # shooters: "
//const char* MenuList[2] ="   Select Delay:    "
//const char* MenuList[3] =" Select # of hits:  "
//const char* MenuList[4] =" Select stop time:  "
//const char* MenuList[5] ="   Save options:    "

//const char* CoFlist[0] = "Standard 1"
//const char* CoFlist[1] = "QuickDraw1"
//const char* CoFlist[2] = "    21    "
//const char* CoFlist[3] = " Custom 1 "
//const char* CoFlist[4] = " Custom 2 "
//const char* CoFlist[5] = " Custom 3 "
//const char* CoFlist[6] = "  A vs B  "

… and put these in instead …

const char* MenuList[] ={"    Select CoF:     "," Select # shooters: ","   Select Delay:    ",
" Select # of hits:  "," Select stop time:  ","   Save options:    "}

const char* CoFlist[] = {"Standard 1","QuickDraw1","    21    "," Custom 1 ",
" Custom 2 "," Custom 3 ","  A vs B  "}

So then the question remains as to whether the const needs to be there or not. These strings aren’t intended to be variables, they won’t change (at least not in the near future) so I thought declaring them to be constants would mean they don’t get assigned RAM locations ?? :?:

dkulinski:
Hope that helps out.

Dan

It does ! Always happpy to have someone looking at this because I’m in over my head at this point.

I figure there are 2 more developmental steps to get the UI working. If the above pans out, the next step is to pass the variables that control the timer setup (1/2 shooters, countdown delay, stop time and hits) to the UI and have the UI alter them and pass them back … or not, depending on the save option choosen. I think I’d like to implement 2 “quick exits”, one that exits w/o altering the aforementioned variables (by having the user hit the start button) and one that exits and uses, but doesn’t save to EEPROM, those variables (so they can be tried out before saving). For this I’ll steal your idea of having the select button continually depressed for 1+ sec. That way the user can avoid having to navigate to the Save options: menu item. But those can wait until all the basic are up and working.

The last development step will be to write and read those saved variables to EEPROM and that will require the defintion of a new structure and implementation of an ‘EEPROMWriteAnything’ technique I saw.

http://arduino.cc/playground/Code/EEPROMWriteAnything

If the UI works after all of the the above, there’s one more “saving memory” build to the yet-to-be-shown-working rev of timer code that sspbass has on his plate right now, before the UI code can be married to the timer code. After that marriage … it’s done ( :liar: ), except for the fine tuning and bug squashing and … :mrgreen:

FWIW : I think we should continue to get the last build of timer code working first, before going onto the UI. I just needed to get some thoughts out of my head and onto “paper”. Plus others can now look at the concept and bones of the UI and hopefully point out where it’s gone off the rails. My instinct is the last timer build is pretty close to working and then I have one more memory saving rev waiting in the wings.

After that we’ll need the UI to be working to make the final timer to “be all it can be”.

Features like double tap detection and individual target recognition will have to come after that … if they ever come.

Because the strings are declared explicitly they aren’t stored in RAM, I don’t think const causes that. You can always compile to assembler and double check it there.

When you define const char * MenuList[0] = “some text” what you are telling the compile is that the value stored in this pointer is constant, not, the data pointed to at this location is constant. const char * const MenuList[0] = “some string” means that both the pointer can’t point to another location AND the data in that location can’t be changed. Remember that MenuList[0] is actually a dereference in itself too. (As a side note I really hate the use of const in regards to pointers. Makes things VERY messy if you are unfamiliar with it.)

EEPROM storage should be pretty simple. I’ll be devling into that too myself on my project but I won’t have the neat little library to make my life a little easier.

Dan

We can get rid of the const in the last post and make it look just like the example. Perhaps that’s the smart thing to do. Start with something that looks just like the example, verify it works and then screw it up while trying to optimize it !

In fact I’ve just changed my copy of the UI to do that !

char* MenuList[] ={"    Select CoF:     "," Select # shooters: ","   Select Delay:    ",
" Select # of hits:  "," Select stop time:  ","   Save options:    "}

//const char* MenuList[0] ="    Select CoF:     "
//const char* MenuList[1] =" Select # shooters: "
//const char* MenuList[2] ="   Select Delay:    "
//const char* MenuList[3] =" Select # of hits:  "
//const char* MenuList[4] =" Select stop time:  "
//const char* MenuList[5] ="   Save options:    "

char* CoFlist[] = {"Standard 1","QuickDraw1","    21    "," Custom 1 ",
" Custom 2 "," Custom 3 ","  A vs B  "}

//const char* CoFlist[0] = "Standard 1"
//const char* CoFlist[1] = "QuickDraw1"
//const char* CoFlist[2] = "    21    "
//const char* CoFlist[3] = " Custom 1 "
//const char* CoFlist[4] = " Custom 2 "
//const char* CoFlist[5] = " Custom 3 "
//const char* CoFlist[6] = "  A vs B  "

Mee_n_Mac:

sspbass:
buffer wasn’t declared. What is it supposed to be set to?

Hmmm, the char buf[6]; is that declaration. What am I missing ? OOOOOOPPPPPS, that “buffer” is supposed to be “buf”.

if (A_count > 1)
  {
    Split = A_Times[A_count-1] - A_Times[A_count-2];
  }
  lcd.print("Split time = ");
  TimeConvert(Split); // convert split time
  lcd.setCursor(0, 3);
  // compute A hit factor
  float HF = A_count/A_Times[A_count - 1];
  lcd.print("Hit factor = ");
  char buf[6];
  PString(buf, sizeof(buf), HF);  // convert FP to char
  lcd.print(buf);
}



Have I said how much I hate coding ?

I’m way the heck back here on this. It’s not liking the PString.

I don’t know what to do as PStrings are supposed to be compatible with 1.0 which is what I’m running.

sspbass:
I’m way the heck back here on this. It’s not liking the PString.

I don’t know what to do as PStrings are supposed to be compatible with 1.0 which is what I’m running.

Well that kinda bites as I was counting on using PString in the UI code. It’s supposed to be a simple, lost “cost” (in memory) way of doing just exactly what I was trying to do. For now comment out that part and let’s see if the rest works.

      // compute A hit factor
      //float HF = A_count/A_Times[A_count - 1];
      //lcd.print("Hit factor = ");
      //char buf[6];
      //PString(buf, sizeof(buf), HF);  // convert FP to char
      //lcd.print(buf);

We didn’t have hit factor before and looks like we still won’t. No great loss.

EDIT : I found a post from the guy who wrote PString library. Seems like we may not even need it to “print” the HF to the LCD. But let’s get everything else working first and then go back to that.

Notes about code:

Standard Mode:

Single Shooter

  1. 20th hit, hit time, and split time do not show up on the main screen hit is sensed and timer stops on 20 but screen never shows it.

  2. Data formatting looks good.

  3. Second round starts with 1 hit already but no times registered and ended on 20 hits. 1st hit didn’t have any time in the review display.

2 Shooters

  1. 1st round counts and shows up to 20 rounds. Second round started with one hit already registered and stopped at 20 hits but only showed 19 on

the main screen. No times just the hit, and when in the review mode the 1st hit was empty.

  1. lines 9, 10, 13, 14, 17 & 18 have a random number in front the line. Line 9 is aligned like the single digit lines but since it’s with the double

digits it’s shifted left one.

Quickdraw

Single Shooter

  1. 1st round is good. 2nd round starts with 1 hit counted as above.

  2. Ended at 6 rounds.

2 shooters.

  1. Same issues as above plus the 1st round ended on 6 hits but only registered 5 on the display.

21

Single Shooter

  1. 1st round works fine, second round has same issues as above with it starting with 1 hit “kind of”.

2 shooters

  1. Same issues as single shooter.