LCD 1602 Upgrade

Hi
I am rebuilding a camera timelapse controller and the original LCD is missing. I am trying to use an LCD 1602 display. It turns on but does not read out. The original is a NHD-0216K3Z-FL-GBW which is no longer available. So the question is how to alter the code for a new LCD display.
I have no coding experience so would like some help if possible please.


The original LCD is connected to Ground, LCD and 5v on a PCB which is on a Arduino Mega.
The new LCD I am assuming would connect to Gnd 5v and SCA and SCL pins on the mega.
As per the LCD in this photo

I am assuming it is needed to set the SCl and SCA pins for readout.

TB3_Black_109_Release1.ino (58.2 KB)

/*

(c) 2015 Brian Burling eMotimo INC


    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.



*/

/*


    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
111 Target - Aux Distance with ability for continuous loop - shorten lean.
Add Stopmotion to Inshot menu
Add Brightness to in shot menu

109 Release Notes

-Fixed Aux reverse to work in all cases
-Added ability to reverse AUX_REV to EEPROM direction.
-Added interval change functionality to in shot menu - don't recommend this is used ever unless your shot is already ruined.  Changing anything mid shot will show.
-Added functionality to use left right to set frame to go to.  Can go forward or back.
-Relaxed tight requirements for joystick absolute centering - check
-Fixed motor feedrate issue when Static Time was maxed out.  If you are maxing out your static time by default, you are not using this setting correctly and hurting your shot!  
-Made Static time a max of Interval minus 0.3 seconds to allow at least a .15 second move - check
-Added abs on feedrate min calc to accommodate spurious overrun negatives on SMS shoots resulting in single long frame delays
-Added check on minimum for video to ensure we don't catch 3PT video moves on min calc.
-Added test against power policy for loop 52 (ext triggering)  
-Added ramping and new motor move to starts and ends (decoupled inputs)
-Added coordinated return to start and three axis moves.
-Updated the motorMoving to accurately assign this
-Broke up move profiles.  Added slow down routine to the move to start/move to end.
-Throttled the calc of the move to respect max jog speeds by axis.  If we hit this we indicates "Speed Limit" on video run screen.  If you hit this, lengthen move and/or decrease ramp
-Added to the Setup Menu the Motor Speed parameter - from 2000 to 20000 max to allow folks to tune.the speeds for AUX.  Pan and Tilt are hardcoded.
-Start delay cleaned up and fixed - now down to the second - also a bailout of CZ to get to 5 seconds so you aren't stuck with accidental long delays
-Add Going to End LCD prompt if heading there.
-Target, Go To End. This now works
-Focus on return to start method.  Pause parameters improved to prevent toggling - added CZ released to check for long holds and released.
-Added new Tab for TB3_InShootMenu - just pauses now and only from progstep 50 (regular SMS)
-Added return to start - just called the same routine from the repeat move at the end of the shot - finds start fine (0's) not sure
*/

/* 

 =========================================
Main Program
 =========================================
 
*/

#include <Wire.h>
#include <SoftwareSerial.h>
#include <EEPROM.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "WiiNunchuck3.h"
#include "NHDLCD9.h"

NHDLCD9 lcd(4, 2, 16);  // desired pin, rows, cols   //BB for LCD

char lcdbuffer1[20];  //this used to be 16, but increased to 20 do to overflow when we moved to Arduino 1.6 (stalled and failed)

const char setup_0[] PROGMEM = "Setup Complete";
const char setup_1[] PROGMEM = "    TB3_109";
const char setup_2[] PROGMEM = "Connect Joystick";
const char setup_3[] PROGMEM = "C-Next Z-Go Back";
const char setup_4[] PROGMEM = "C-Use Stored";
const char setup_5[] PROGMEM = "Z-Reset";
const char setup_6[] PROGMEM = "Params Reset";
const char setup_7[] PROGMEM = "Low Power";
const char setup_8[] PROGMEM = "Move to Start Pt";
const char setup_9[] PROGMEM = "Start Pt. Set";
const char setup_10[] PROGMEM = "Move to Point";
const char setup_11[] PROGMEM = "Moving to stored";
const char setup_12[] PROGMEM = "end point";
const char setup_13[] PROGMEM = "Confirm or Move";
const char setup_14[] PROGMEM = "C-Next";
const char setup_15[] PROGMEM = "Move to End Pt.";
const char setup_16[] PROGMEM = "End Point Set";
const char setup_17[] PROGMEM = "Set Sht Interval";
const char setup_18[] PROGMEM = "Intval:   .  sec";
const char setup_19[] PROGMEM = " Ext.Trig";
const char setup_20[] PROGMEM = " Video   ";
const char setup_21[] PROGMEM = "Interval Set";
const char setup_22[] PROGMEM = "Set Static Time";
const char setup_23[] PROGMEM = "Stat_T:   .  sec";
const char setup_24[] PROGMEM = " Video   ";
const char setup_25[] PROGMEM = "Static Time Set";
const char setup_26[] PROGMEM = "Set PreFire Time";
const char setup_27[] PROGMEM = " Pre_T:   .  sec";
const char setup_28[] PROGMEM = "Prefire Time Set";
const char setup_29[] PROGMEM = "    Set Ramp";
const char setup_30[] PROGMEM = "Ramp:     Frames";
const char setup_31[] PROGMEM = "Ramp Set";
const char setup_32[] PROGMEM = "Set Move";
const char setup_33[] PROGMEM = "Duration";
const char setup_34[] PROGMEM = "H:MM:SS";
const char setup_35[] PROGMEM = "Duration Set";
const char setup_36[] PROGMEM = "Set Static Lead";
const char setup_37[] PROGMEM = "In/Out Frames";
const char setup_38[] PROGMEM = "In      Out";
const char setup_39[] PROGMEM = "Lead Frames Set";
const char setup_40[] PROGMEM = " Going to Start";
const char setup_41[] PROGMEM = "Review and";
const char setup_42[] PROGMEM = "Confirm Setting";
const char setup_43[] PROGMEM = "Pan Steps:";
const char setup_44[] PROGMEM = "Tilt Steps:";
const char setup_45[] PROGMEM = "Cam Shots:";
const char setup_46[] PROGMEM = "Time:";
const char setup_47[] PROGMEM = "Ready?";
const char setup_48[] PROGMEM = "Press C Button";
const char setup_49[] PROGMEM = "Program Running";
const char setup_50[] PROGMEM = "Waiting for Ext.";
const char setup_51[] PROGMEM = "LeadIn";
const char setup_52[] PROGMEM = "RampUp";
const char setup_53[] PROGMEM = "Linear";
const char setup_54[] PROGMEM = "RampDn";
const char setup_55[] PROGMEM = "LeadOT";
const char setup_56[] PROGMEM = "Finish";
const char setup_57[] PROGMEM = "Center Joystick";
const char setup_58[] PROGMEM = "Program Complete";
const char setup_59[] PROGMEM = " Repeat Press C";
const char setup_60[] PROGMEM = "Battery too low";
const char setup_61[] PROGMEM = "  to continue";
const char setup_62[] PROGMEM = "Pause ";
const char setup_63[] PROGMEM = "Point X Set";
const char setup_64[] PROGMEM = "Using Set Params";
const char setup_65[] PROGMEM = "UpDown  C-Select";
const char setup_66[] PROGMEM = "New   Point Move";
const char setup_67[] PROGMEM = "Enabled";
const char setup_68[] PROGMEM = "Disabled";
const char setup_69[] PROGMEM = "PowerSave";
const char setup_70[] PROGMEM = "Always";
const char setup_71[] PROGMEM = "Program";
const char setup_72[] PROGMEM = "Shoot (accuracy)";
const char setup_73[] PROGMEM = "Shoot (pwr save)";
const char setup_74[] PROGMEM = "Aux Motor:";
const char setup_75[] PROGMEM = "Set Angle o'View";
const char setup_76[] PROGMEM = "C-Set, Z-Reset";
const char setup_77[] PROGMEM = "Pan AOV: ";
const char setup_78[] PROGMEM = "Tilt AOV: ";
const char setup_79[] PROGMEM = "   % Overlap";
const char setup_80[] PROGMEM = "Overlap Set";
const char setup_81[] PROGMEM = "Rev   Point Move";
const char setup_82[] PROGMEM = "DF Slave Mode";
const char setup_83[] PROGMEM = "Setup Menu";  //not sure why this fails
const char setup_84[] PROGMEM = "Panorama";
const char setup_85[] PROGMEM = "AuxDistance";
const char setup_86[] PROGMEM = "Resume";
const char setup_87[] PROGMEM = "Restart";
const char setup_88[] PROGMEM = "Go to Frame";
const char setup_89[] PROGMEM = "Go to End";
const char setup_90[] PROGMEM = "90";



//PROGMEM const char *setup_str[] = {setup_0,setup_1,setup_2,setup_3,setup_4,setup_5,setup_6,setup_7,setup_8,setup_9,setup_10,
PGM_P const setup_str[] PROGMEM = { setup_0, setup_1, setup_2, setup_3, setup_4, setup_5, setup_6, setup_7, setup_8, setup_9, setup_10,
                                    setup_11, setup_12, setup_13, setup_14, setup_15, setup_16, setup_17, setup_18, setup_19, setup_20,
                                    setup_21, setup_22, setup_23, setup_24, setup_25, setup_26, setup_27, setup_28, setup_29, setup_30,
                                    setup_31, setup_32, setup_33, setup_34, setup_35, setup_36, setup_37, setup_38, setup_39, setup_40,
                                    setup_41, setup_42, setup_43, setup_44, setup_45, setup_46, setup_47, setup_48, setup_49, setup_50,
                                    setup_51, setup_52, setup_53, setup_54, setup_55, setup_56, setup_57, setup_58, setup_59, setup_60,
                                    setup_61, setup_62, setup_63, setup_64, setup_65, setup_66, setup_67, setup_68, setup_69, setup_70,
                                    setup_71, setup_72, setup_73, setup_74, setup_75, setup_76, setup_77, setup_78, setup_79, setup_80,
                                    setup_81, setup_82, setup_83, setup_84, setup_85, setup_86, setup_87, setup_88, setup_89, setup_90 };


//Global Parameters
#define DEBUG 0        //
#define DEBUG_MOTOR 0  //
#define DEBUG_NC 0     //
#define DEBUG_PANO 0
#define DEBUG_GOTO 0
#define POWERDOWN_LV false  //set this to cause the TB3 to power down below 10 volts
#define MAX_MOVE_POINTS 3
#define VIDEO_FEEDRATE_NUMERATOR 375L  // Set this for 42000L, or 375L for faster calc moves
#define PAN_MAX_JOG_STEPS_PER_SEC 10000.0
#define TILT_MAX_JOG_STEPS_PER_SEC 10000.0
//#define AUX_MAX_JOG_STEPS_PER_SEC 15000.0 //this is defined in the setup menu now.


//Main Menu Ordering

#define MENU_OPTIONS 8


#define REG2POINTMOVE 0
#define REV2POINTMOVE 1
#define REG3POINTMOVE 2
#define REV3POINTMOVE 3
#define PANOGIGA 4
#define PORTRAITPANO 5
#define DFSLAVE 6
#define SETUPMENU 7
#define AUXDISTANCE 99



//Portrait Pano
#define PanoArrayTypeOptions 5

#define PANO_9ShotCenter 1
#define PANO_25ShotCenter 3
#define PANO_7X3 2
#define PANO_9X5Type1 6
#define PANO_9X5Type2 7
#define PANO_5x5TopThird 4
#define PANO_7X5TopThird 5

//In Program Menu Ordering
#define INPROG_OPTIONS 5  //up this when code for gotoframe

#define INPROG_RESUME 0
#define INPROG_RTS 1          //return to start
#define INPROG_GOTO_END 2     //Go to end
#define INPROG_GOTO_FRAME 3   //go to frame
#define INPROG_INTERVAL 4     //Set Interval
#define INPROG_STOPMOTION 99  //Manual Forward and Back

//Interval Options
#define VIDEO_INTVAL 2
#define EXTTRIG_INTVAL 3
#define MIN_INTERVAL_STATIC_GAP 3  //min gap between interval and static time
//#define STOPMOT //not used

//TB3 section - Black or Orange Port Mapping for Step pins on Stepper Page
#define MOTORS 3
#define MOTOR0_STEP 5
#define MOTOR1_STEP 6
#define MOTOR2_STEP 7
#define MOTOR0_DIR 8
#define MOTOR1_DIR 9
#define MOTOR2_DIR 10
#define MOTOR_EN A3
#define MOTOR_EN2 11
#define MS1 A1
#define MS2 A2
#define MS3 A2
#define IO_2 2                 // drives middle of 2.5 mm connector on I/O port
#define IO_3 3                 // drives tip of 2.5 mm connector on I/O port
#define CAMERA_PIN 12          // drives tip of 2.5 mm connector
#define FOCUS_PIN 13           // drives  middle of 2.5mm connector
#define STEPS_PER_DEG 444.444  //160000 MS per 360 degees = 444.4444444

/*
STEPS_PER_INCH_AUX for various motors with 17 tooth final gear on 5mm pitch belt
Phidgets 99:1	95153
Phidgets 27:1	25676
Phidgets 5:1	4955
20:1 Ratio	19125
10:1 Ratio	9562
*/

#define STEPS_PER_INCH_AUX 19125   //
#define MAX_AUX_MOVE_DISTANCE 311  //(31.1 inches)
//end TB3 section

unsigned long build_version = 10951;     //this value is compared against what is stored in EEPROM and resets EEPROM and setup values if it doesn't match
unsigned int intval = 2;                 //seconds x10  - used for the interval prompt and display
unsigned long interval = 2000;           //calculated and is in ms
unsigned int camera_fired = 0;           //number of shots fired
unsigned int camera_moving_shots = 200;  //frames for new duration/frames prompt
unsigned int camera_total_shots = 0;     //used at the end target for camera fired to compare against
unsigned int overaldur = 20;             //seconds now for video only
unsigned int prefire_time = 1;           //currently hardcoded here to .1 second - this powers up motor early for the shot
unsigned int rampval = 50;
unsigned int static_tm = 1;  //new variable
unsigned int lead_in = 1;
unsigned int lead_out = 1;
unsigned int start_delay_sec = 0;
int aux_dist;

//External Interrupt Variables
volatile int state = 0;                   //new variable for interrupt
volatile boolean changehappened = false;  //new variable for interrupt
long shuttertimer_open = 0;
long shuttertimer_close = 0;
boolean ext_shutter_open = false;
int ext_shutter_count = 0;
int ext_hdr_shots = 1;  //this is how many shots are needed before moving - leave at one for normal shooting - future functionality with external

//Start of variables for Pano Mode
unsigned int P2PType = 1;  // 0 = no accel, 1= accel
unsigned int PanoPostMoveDelay = 200;

//3 Point motor routine values
float motor_steps_pt[MAX_MOVE_POINTS][MOTORS];                                 // 3 total points.   Start point is always 0.0
float percent;                                                                 //% through a leg
unsigned int keyframe[2][6] = { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 } };  //this is basically the keyframes {start, end of rampup, start or rampdown, end}   - doesn't vary by motor at this point
float linear_steps_per_shot[MOTORS] = { 0.0, 0.0, 0.0 };                       //{This is for the calculated or estimated steps per shot in a segment for each motor
float ramp_params_steps[MOTORS] = { 0.0, 0.0, 0.0 };                           //This is to calc the steps at the end of rampup for each motor.  Each array value is for a motor

//Program Status Flags
boolean Program_Engaged = false;
boolean Shot_Sequence_Engaged = false;
boolean Prefire_Engaged = false;
boolean Shutter_Signal_Engaged = false;
boolean Static_Time_Engaged = false;
boolean IO_Engaged = false;
boolean Move_Engaged = false;
boolean Interrupt_Fire_Engaged = false;

//Timer2flags
unsigned long MsTimer2_msecs;
//void (*MsTimer2_func)();
volatile unsigned long MsTimer2_count;
volatile char MsTimer2_overflowing;
volatile unsigned int MsTimer2_tcnt2;

//New Powersave flags
/*Power Save explanation
We can power up and power down the Pan Tilt motors together.  We can power up and power down the Aux motor port as well.  We see three levels of power saving:
1)  None - Motors are always on - for VFX work where power isn't a factor and precision is most important.  Motors will get warm here on hot days.
2)  Low - only at the end of program 
3)  Standard - Power up the motors for the shooting time (all the time we hold the trigger down), and move, power down between shots.
4)  High - Only power on for motor moves, turn off the motors when we reach the shooting position.  
    We are powered down for the shot and only power on for moves. This saves a ton of battery for long astro shots.   
    We do lose microstep resolution for this, but it usually is not visible.   We could be off by as much as 8/16 mircosetps for a shot or 0.018 degrees - Really small stuff!  Try this mode out!
*/


//CVariables that are set during the Setup Menu store these in EEPROM
unsigned int POWERSAVE_PT;   //1=None - always on  2 - low   3=standard    4=High
unsigned int POWERSAVE_AUX;  //1=None - always on  2 - low   3=standard    4=High
byte AUX_ON;                 //1=Aux Enabled, 2=Aux disabled
byte PAUSE_ENABLED;          //1=Pause Enabled, 0=Pause disabled
boolean REVERSE_PROG_ORDER;  //Program ordering 0=normal, start point first. 1=reversed, set end point first to avoid long return to start
boolean MOVE_REVERSED_FOR_RUN = 0;
unsigned int LCD_BRIGHTNESS_DURING_RUN;  //0 is off 8 is max
unsigned int AUX_MAX_JOG_STEPS_PER_SEC;  //value x 1000  20 is the top or 20000 steps per second.
byte AUX_REV;                            //1=Aux Enabled, 2=Aux disabled


//control variable, no need to store in EEPROM - default and setup during shot
unsigned int progstep = 0;            //used to define case for main loop
boolean progstep_forward_dir = true;  //boolean to define direction of menu travel to allow for easy skipping of menus
unsigned int progtype = 0;            //updownmenu selection
int inprogtype = 0;                   //updownmenu selection during shoot
boolean reset_prog = 1;               //used to handle program reset or used stored
unsigned int first_time = 1;          //variable to help with LCD dispay variable that need to show one time
boolean first_time2 = true;
int batt_low_cnt = 0;
unsigned int max_shutter;
unsigned int max_prefire;
unsigned int program_progress_2PT = 1;  //Lead in, ramp, linear, etc for motor routine case statement
unsigned int program_progress_3PT = 1;  //phase 1, phase 2
unsigned long interval_tm = 0;          //mc time to help with interval comparison
unsigned long interval_tm_last = 0;     //mc time to help with interval comparison
int cursorpos = 1;                      //use 1 for left, 2 for right  - used for lead in, lead out
unsigned int lcd_dim_tm = 10;
unsigned long input_last_tm = 0;
unsigned long diplay_last_tm = 0;
unsigned int lcd_backlight_cur = 100;
unsigned int prompt_time = 500;  // in ms for delays of instructions
//unsigned int  prompt_time=350; // for faster debugging
int prompt_delay = 0;  //to help with joystick reads and delays for inputs - this value is set during joystick read and executed later in the loop
int prompt_val;
unsigned int video_sample_ms = 100;  //
unsigned int video_segments = 150;   //arbitrary
int reviewprog = 1;
//variables for display of remaining time
int timeh;
int timem;
int time_s;

unsigned long start_delay_tm = 0;  //ms timestamp to help with delay comparison
unsigned int goto_shot = 0;

int sequence_repeat_type = 1;   //1 Defaults - Run Once, 0 Continuous Loop,  -1 Continuous Forward
int sequence_repeat_count = 0;  //counter to hold variable for how many time we have repeated



//remote and interface variables

float joy_x_axis;
int joy_x_axis_Offset;
int joy_x_axis_Bucket;
int joy_x_axis_Threshold;
int joy_x_axis_map;
int speedx;
float joy_y_axis;
int joy_y_axis_Offset;
int joy_y_axis_Bucket;
int joy_y_axis_Threshold;
int joy_y_axis_map;
int speedy;
float accel_x_axis;
int accel_x_axis_Offset;
int accel_x_axis_Bucket;
int accel_x_axis_Threshold;

int PanStepCount;
int TiltStepCount;

int z_button = 0;
int c_button = 0;
int prev_joy_x_reading = 0;
int prev_joy_y_reading = 0;
unsigned int joy_y_lock_count = 0;
unsigned int joy_x_lock_count = 0;
int prev_accel_x_reading = 0;
int CZ_Button_Read_Count = 0;
boolean CZ_Released = true;
int C_Button_Read_Count = 0;
boolean C_Released = true;
int Z_Button_Read_Count = 0;
boolean Z_Released = true;
int NCReadStatus = 0;            //control variable for NC error handling
unsigned int NCReadMillis = 42;  //frequency at which we read the nunchuck for moves  1000/24 = 42  1000/30 = 33
long NClastread = 1000;          //control variable for NC reads cycles




//Stepper Setup
unsigned long feedrate_micros = 0;

struct FloatPoint {
  float x;
  float y;
  float z;
};
FloatPoint fp;

FloatPoint current_steps;
FloatPoint target_steps;
FloatPoint delta_steps;

//our direction vars
byte x_direction = 1;
byte y_direction = 1;
byte z_direction = 1;

//End setup of Steppers

//Start of DF Vars
#define DFMOCO_VERSION 1
#define DFMOCO_VERSION_STRING "1.2.6"


// supported boards
#define ARDUINO 1
#define ARDUINOMEGA 2

//eMotimo TB3 - Set this PINOUT_VERSION 3 for TB3 Orange (Uno)
//eMotimo TB3 - Set this PINOUT_VERSION 4 for TB3 Black (MEGA)
#define PINOUT_VERSION 4

/*
  This is PINOUT_VERSION 1
  
  channel 5
        PIN  22   step
        PIN  23   direction
  channel 6
        PIN  24   step
        PIN  25   direction
  channel 7
        PIN  26   step
        PIN  27   direction
  channel 8
        PIN  28   step
        PIN  29   direction
*/

// detect board type
#define BOARD ARDUINOMEGA

#define SERIAL_DEVICE Serial

#define PIN_ON(port, pin) \
  { port |= pin; }
#define PIN_OFF(port, pin) \
  { port &= ~pin; }

#define MOTOR_COUNT 4

#define TIME_CHUNK 50
#define SEND_POSITION_COUNT 20000

// update velocities 20 x second
#define VELOCITY_UPDATE_RATE (50000 / TIME_CHUNK)
#define VELOCITY_INC(maxrate) (max(1.0f, maxrate / 70.0f))


//Start TB3 Black Port Mapping

#define MOTOR0_STEP_PORT PORTE
#define MOTOR0_STEP_PIN B00001000  //Pin 5 PE3

#define MOTOR1_STEP_PORT PORTH
#define MOTOR1_STEP_PIN B00001000  //Pin  6 PH3

#define MOTOR2_STEP_PORT PORTH
#define MOTOR2_STEP_PIN B00010000  //Pin 7 PH4

#define MOTOR3_STEP_PORT PORTC     //  Map this to pin 30 PC7 on the Mega board for debug
#define MOTOR3_STEP_PIN B10000000  //
//End TB3 Black Port Mapping


/**
 * Serial output specialization
 */
#if defined(UBRRH)
#define TX_UCSRA UCSRA
#define TX_UDRE UDRE
#define TX_UDR UDR
#else
#define TX_UCSRA UCSR0A
#define TX_UDRE UDRE0
#define TX_UDR UDR0
#endif

char txBuf[32];
char* txBufPtr;

#define TX_MSG_BUF_SIZE 16

#define MSG_STATE_START 0
#define MSG_STATE_CMD 1
#define MSG_STATE_DATA 2
#define MSG_STATE_ERR 3

#define MSG_STATE_DONE 100

/*
 * Command codes from user
 */
#define USER_CMD_ARGS 40

#define CMD_NONE 0
#define CMD_HI 10
#define CMD_MS 30
#define CMD_NP 31
#define CMD_MM 40  // move motor
#define CMD_PR 41  // pulse rate
#define CMD_SM 42  // stop motor
#define CMD_MP 43  // motor position
#define CMD_ZM 44  // zero motor
#define CMD_SA 50  // stop all (hard)
#define CMD_BF 60  // blur frame
#define CMD_GO 61  // go!

#define CMD_JM 70  // jog motor
#define CMD_IM 71  // inch motor

#define MSG_HI 01
#define MSG_MM 02
#define MSG_MP 03
#define MSG_MS 04
#define MSG_PR 05
#define MSG_SM 06
#define MSG_SA 07
#define MSG_BF 10
#define MSG_GO 11
#define MSG_JM 12
#define MSG_IM 13


struct UserCmd {
  byte command;
  byte argCount;
  int32_t args[USER_CMD_ARGS];
};

/*
 * Message state machine variables.
 */
byte lastUserData;
int msgState;
int msgNumberSign;
UserCmd userCmd;


struct txMsg {
  byte msg;
  byte motor;
};

struct TxMsgBuffer {
  txMsg buffer[TX_MSG_BUF_SIZE];
  byte head;
  byte tail;
};

TxMsgBuffer txMsgBuffer;


/*
 Motor data.
 */

uint16_t motorAccumulator0;
uint16_t motorAccumulator1;
uint16_t motorAccumulator2;
uint16_t motorAccumulator3;

uint16_t* motorAccumulator[MOTOR_COUNT] = {
  &motorAccumulator0,
  &motorAccumulator1,
  &motorAccumulator2,
  &motorAccumulator3,

};

uint16_t motorMoveSteps0;
uint16_t motorMoveSteps1;
uint16_t motorMoveSteps2;
uint16_t motorMoveSteps3;

uint16_t* motorMoveSteps[MOTOR_COUNT] = {
  &motorMoveSteps0,
  &motorMoveSteps1,
  &motorMoveSteps2,
  &motorMoveSteps3,
};


uint16_t motorMoveSpeed0;
uint16_t motorMoveSpeed1;
uint16_t motorMoveSpeed2;
uint16_t motorMoveSpeed3;

uint16_t* motorMoveSpeed[MOTOR_COUNT] = {
  &motorMoveSpeed0,
  &motorMoveSpeed1,
  &motorMoveSpeed2,
  &motorMoveSpeed3,

};

volatile boolean nextMoveLoaded;


unsigned int velocityUpdateCounter;
byte sendPositionCounter;
boolean hardStopRequested;

byte sendPosition = 0;
byte motorMoving = 0;
byte toggleStep = 0;


#define P2P_MOVE_COUNT 7

struct Motor {
  byte stepPin;
  byte dirPin;

  // pre-computed move
  float moveTime[P2P_MOVE_COUNT];
  int32_t movePosition[P2P_MOVE_COUNT];
  float moveVelocity[P2P_MOVE_COUNT];
  float moveAcceleration[P2P_MOVE_COUNT];

  float gomoMoveTime[P2P_MOVE_COUNT];
  int32_t gomoMovePosition[P2P_MOVE_COUNT];
  float gomoMoveVelocity[P2P_MOVE_COUNT];
  float gomoMoveAcceleration[P2P_MOVE_COUNT];

  int currentMove;
  float currentMoveTime;

  volatile boolean dir;

  int32_t position;
  int32_t destination;

  float maxVelocity;      //Orig - delete later
  float maxAcceleration;  //Orig - delete later

  float moveMaxVelocity;      //Pass this into calculator for synchronized moves
  float moveMaxAcceleration;  //Pass this into calculator for synchronized moves

  float jogMaxVelocity;      //replaced the original maxVelocity
  float jogMaxAcceleration;  //replaced the original maxAcceleration

  uint16_t nextMotorMoveSteps;
  float nextMotorMoveSpeed;
};

boolean maxVelLimit = false;

boolean goMoReady;
int goMoDelayTime;

Motor motors[MOTOR_COUNT];

//End of DFVars


/* 
 =========================================
 Setup functions
 =========================================
*/



void setup() {

  // setup motor pins
  pinMode(MOTOR0_STEP, OUTPUT);
  pinMode(MOTOR0_DIR, OUTPUT);
  pinMode(MOTOR1_STEP, OUTPUT);
  pinMode(MOTOR1_DIR, OUTPUT);
  pinMode(MOTOR2_STEP, OUTPUT);
  pinMode(MOTOR2_DIR, OUTPUT);

  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(MS3, OUTPUT);

  digitalWrite(MS1, HIGH);
  digitalWrite(MS2, HIGH);
  digitalWrite(MS3, HIGH);

  pinMode(MOTOR_EN, OUTPUT);
  pinMode(MOTOR_EN2, OUTPUT);
  digitalWrite(MOTOR_EN, HIGH);   //LOW Enables output, High Disables
  digitalWrite(MOTOR_EN2, HIGH);  //LOW Enables output, High Disables

  // setup camera pins
  pinMode(CAMERA_PIN, OUTPUT);
  pinMode(FOCUS_PIN, OUTPUT);

  digitalWrite(CAMERA_PIN, LOW);
  digitalWrite(FOCUS_PIN, LOW);

  //Setup of I/0 Pings Start with output of I/Oport
  pinMode(IO_2, OUTPUT);
  pinMode(IO_3, OUTPUT);

  digitalWrite(IO_2, LOW);
  digitalWrite(IO_3, LOW);

  pinMode(A0, INPUT);  //this is for the voltage reading

  //Setup LCD
  lcd.setup();
  delay(100);
  draw(0, 1, 2);  // Setup Complete
  draw(1, 2, 1);  // Version Number
  //strcpy_P(lcdbuffer1, (PGM_P)pgm_read_word(&(setup_str[0]))); // Necessary casts and dereferencing, just copy.
  //lcd.at(2,1,lcdbuffer1);
  lcd.contrast(50);
  lcd.cursorOff();
  lcd.bright(4);

  delay(prompt_time * 2);
  lcd.empty();
  delay(100);

  draw(2, 1, 1);  // Connect Joystick

  //Setup Serial Connection

  //if (DEBUG) Serial.begin(115200);
  //else Serial.begin(57600);
  Serial.begin(57600);
  Serial.println("Opening Serial Port");

  // Handle EEPROM Interaction and upgrades

  //Check to see if our hardcoded build version set in progam is different than what was last put in EEPROM - detect upgrade.
  if (build_version != check_version()) {  //4 byte string that now holds the build version.
    if (DEBUG) Serial.println(check_version());
    if (DEBUG) Serial.println("Upgrading Memory");
    write_defaults_to_eeprom_memory();  //these are for setting for last shot
    set_defaults_in_setup();            //this is for our setup values that should only be defaulted once.
    //review_RAM_Contents();
  } else {  //load last setting into memory - no upgrade
    if (DEBUG) Serial.println("Restoring EEPROM Values");
    restore_from_eeprom_memory();
    //review_RAM_Contents();
  }
  //End Setup of EEPROM

  //begin  Setup for Nunchuck
  Nunchuck.init(0);
  delay(50);
  for (int reads = 1; reads < 17; reads++) {
    Nunchuck.getData();
    //Nunchuck.printData();
    lcd.at(2, reads, "+");
    if (abs(Nunchuck.joyx() - 127) > 60 || abs(Nunchuck.joyy() - 127) > 60) {
      lcd.empty();
      draw(57, 1, 1);  //lcd.at(1,1,"Center Joystick");
      reads = 1;
    }
    delay(10);
  }

  calibrate_joystick(Nunchuck.joyx(), Nunchuck.joyy());

  //end  Setup for Nunchuk
  lcd.empty();


  //Setup Motors
  init_steppers();

  //init_external_triggering();
  pinMode(IO_3, INPUT);
  digitalWrite(IO_3, HIGH);
  attachInterrupt(1, cam_change, CHANGE);



}  //end of setup

void loop() {  //Main Loop
  while (1) {  //use debugging WHEN HIT here for monitoring - {sequence_repeat_type},{progstep},{progtype},{camera_fired}
    switch (progstep) {

        //start of 2 point SMS/Video routine
      case 0:  //
        Choose_Program();

        break;

      case 1:                  // Move to Start Point
        Move_to_Startpoint();  //don't jump in this loop by accident
        break;

      case 2:                // Move to End Point
        Move_to_Endpoint();  //don't jump in this loop by accident
        break;

      case 3:  //  Set Camera Interval
        Set_Cam_Interval();
        break;

      case 4:  //
        Set_Duration();
        break;

      case 5:  //  	    Static Time

        if (intval == VIDEO_INTVAL) {                    //don't show this for video
          if (progstep_forward_dir) progstep_forward();  //skip the menu, go forward
          else progstep_backward();                      //skip the menu, go backward
        } else Set_Static_Time();                        //not needed for video

        break;

      case 6:  //

        Set_Ramp();

        break;

      case 7:  //  Lead in and lead out

        if (intval == VIDEO_INTVAL) {  //don't show this for video
          if (progstep_forward_dir) {
            Calculate_Shot();  //
            progstep_forward();
          }  //skip the menu, go forward
          else
            progstep_backward();  //skip the menu, go backward
        }

        else Set_LeadIn_LeadOut();  //  not needed for video


        break;

      case 8:                          //  Set Shot Type
        if (intval != VIDEO_INTVAL) {  //skip for non video
          if (progstep_forward_dir) {
            progstep_forward();        //skip the menu, go forward
          } else progstep_backward();  //skip the menu, go backward
        }

        else Set_Shot_Repeat();
        break;

      case 9:              //  review and confirm
        Review_Confirm();  //also has the delay start options here
        break;

        //end of the two point move

        //start of the three point move
      case 100:
        Choose_Program();
        break;

      case 101:  // Move Point 0
        Move_to_Point_X(0);
        break;

      case 102:  // Move Point 1
        Move_to_Point_X(1);
        break;

      case 103:  // Move Point 2
        Move_to_Point_X(2);
        break;

      case 104:  //  Set Camera Interval
        Set_Cam_Interval();
        break;

      case 105:  //
        Set_Duration();
        break;

      case 106:  //
        Set_Static_Time();
        break;

      case 107:  //
        Set_Ramp();
        break;

      case 108:  //
        Set_LeadIn_LeadOut();
        break;

      case 109:  //  review and confirm
        Review_Confirm();
        break;
        //end of the three point move

        //start of pano Mode

        //  define field of view
        //We want to know how wide and tall our field of view is in steps so we can get our overlap right.  Anytime you zoom or change lenses, this need to be redefined
        //This should be a 10 seconds process to define by specifying corners
        //Step 1 - Put a point in the upper right corner - set zeros, pan up and right to hit same point with lower left corner of viewfinder
        //Display values  - write to ram - use these values

      case 200:  //
        Choose_Program();
        break;

      case 201:              //
        Move_to_Point_X(0);  //move to sharp point
        break;

      case 202:  //
        Set_angle_of_view();
        break;

      case 203:  //
        Define_Overlap_Percentage();
        break;

      case 204:  //
        Move_to_Point_X(0);
        break;

      case 205:  //
        Move_to_Point_X(1);
        break;

      case 206:  //
        Set_Static_Time();
        break;

      case 207:  //
        Pano_Review_Confirm();
        break;
        //end of Pano Mode



        //start of Portrait Pano Method

        //  define field of view
        //We want to know how wide and tall our field of view is in steps so we can get our overlap right.  Anytime you zoom or change lenses, this need to be redefined
        //This should be a 10 seconds process to define by specifying corners
        //Step 1 - Put a point in the upper right corner - set zeros, pan up and right to hit same point with lower left corner of viewfinder
        //Display values  - write to ram - use these values

      case 210:  //
        Choose_Program();
        break;

      case 211:              //
        Move_to_Point_X(0);  //move to sharp point
        break;

      case 212:  //
        Set_angle_of_view();
        break;

      case 213:  //
        Define_Overlap_Percentage();
        break;

      case 214:              //
        Move_to_Point_X(0);  //set subject point
        break;

      case 215:               //
        Set_PanoArrayType();  //this sets variable that define how we move camera - load the appropriate array.
        break;

      case 216:  //
        Set_Static_Time();
        break;

      case 217:  //
        Pano_Review_Confirm();
        break;
        //end of Pano Mode




        //start of entered distance on aux mode
      case 300:  //
        Choose_Program();
        break;

      case 301:  // Move to Start Point
        Move_to_Startpoint();
        break;

      case 302:  // Move to End Point
        Enter_Aux_Endpoint();
        break;

      case 303:  //  Set Camera Interval
        Set_Cam_Interval();
        break;

      case 304:  //
        Set_Duration();
        break;

      case 305:  //
        Set_Static_Time();
        break;

      case 306:  //
        Set_Ramp();
        break;

      case 307:  //
        Set_LeadIn_LeadOut();
        break;

      case 308:  //  review and confirm
        Review_Confirm();
        break;

        //end entered distance mode

        //start of setup

      case 901:  // AUX_ON
        Setup_AUX_ON();
        break;

      case 902:  // PAUSE_ENABLED
        Setup_PAUSE_ENABLED();
        break;

      case 903:  // POWERSAVE_PT
        Setup_POWERSAVE_PT();
        break;

      case 904:  //  POWERSAVE_AUX
        Setup_POWERSAVE_AUX();
        break;

      case 905:  //  LCD Bright
        Setup_LCD_BRIGHTNESS_DURING_RUN();
        break;

      case 906:  //  Aux Motor Max Speed
        Setup_Max_AUX_Motor_Speed();
        break;

      case 907:  //  LCD Bright
        Setup_AUX_Motor_DIR();
        break;


      case 908:  //  Exit
        delay(100);
        break;


        //end of setup

        //start of in program menu options

      case 1001:  // AUX_ON
        InProg_Select_Option();
        break;




        //end of in program menu



      case 50:  // loop for SMS

        // //Step 1 if internal interval.Kick off the shot sequence. This happens once per camera shot.
        if ((intval > 3) && (Program_Engaged) && !(Shot_Sequence_Engaged) && ((millis() - interval_tm) > interval)) {
          interval_tm_last = interval_tm;  //just used for shot timing comparison
          interval_tm = millis();          //start the clock on our shot sequence

          if (DEBUG) {
            Serial.print("trueinterval: ");
            Serial.print(interval_tm - interval_tm_last);
            Serial.print(";");
          }
          Interrupt_Fire_Engaged = false;  //clear this flag to avoid rentering this routine
          Shot_Sequence_Engaged = true;    //
          Prefire_Engaged = true;          //
          IO_Engaged = true;               //
          digitalWrite(FOCUS_PIN, HIGH);   //for longer shot interval, wake up the camera

          if (POWERSAVE_PT < 4) enable_PT();              //don't power on for shot for high power saving
          if (AUX_ON && POWERSAVE_AUX < 4) enable_AUX();  //don't power on for shot for high power saving
        }

        //Step 1 if external triggering. This happens once per camera shot.
        if ((Program_Engaged) && !(Shot_Sequence_Engaged) && (intval == EXTTRIG_INTVAL) && Interrupt_Fire_Engaged) {
          interval_tm_last = interval_tm;  //just used for shot timing comparison

          interval_tm = millis();  //start the clock on our shot sequence
          if (DEBUG) {
            Serial.print("trueinterval: ");
            Serial.print(interval_tm - interval_tm_last);
            Serial.print(";");
          }
          Interrupt_Fire_Engaged = false;  //clear this flag to avoid rentering this routine

          Shot_Sequence_Engaged = true;   //
          Prefire_Engaged = true;         //
          IO_Engaged = true;              //
          digitalWrite(FOCUS_PIN, HIGH);  //for longer shot interval, wake up the camera

          if (POWERSAVE_PT < 4) enable_PT();              //don't power on for shot for high power saving
          if (AUX_ON && POWERSAVE_AUX < 4) enable_AUX();  //don't power on for shot for high power saving
        }


        //End our prefire - check that we are in program active,shot cycle engaged, and prefire engaged and check against our prefire time
        //If so set prefire flag off, static flag on, fire camera for static time value, update the display

        if ((Shot_Sequence_Engaged) && (Prefire_Engaged) && ((millis() - interval_tm) > prefire_time * 100)) {

          Prefire_Engaged = false;
          if (DEBUG) {
            Serial.print("PreDoneAt ");
            Serial.print(millis() - interval_tm);
            Serial.print(";");
          }

          Static_Time_Engaged = true;
          //Fire Camera
          if (intval != 3) fire_camera((long)static_tm * 100);  //start shutter sequence
          camera_fired++;
        }

        //End out static time - check that we are in an program active and static time,  Shutter not engaged, check shot cycle time agains prefire+statictime
        //If so remove flags from Static Time Engaged and IO engaged, Turn off I/O port, set flags for motors moving, move motors
        //move motors - figure out delays.   Long delays mean really slow - choose the minimum of the calculated or a good feedrate that is slow

        //if (Program_Engaged && Shot_Sequence_Engaged && Static_Time_Engaged && !Shutter_Signal_Engaged && ((millis() - interval_tm) > (prefire_time*100+static_tm*100)) ) {
        if (Shot_Sequence_Engaged && Static_Time_Engaged && !Shutter_Signal_Engaged && ((millis() - interval_tm) > (prefire_time * 100 + static_tm * 100))) {  //removed requirement for Program Engaged for external interrupt


          Static_Time_Engaged = false;  //Static Time Engaged is OFF
          IO_Engaged = false;           //IO Engaged is off
          //digitalWrite(IO_2, LOW); //Use this as the iterrupt
          //digitalWrite(IO_3, LOW);  //Turn off Pin 3
          //Serial.print("IO3_off"); //Serial.println(millis()-interval_tm);


          //Move the motors - each motor move is calculated by where we are in the sequence - we still call this for lead in and lead out - motors just don't move

          Move_Engaged = true;  //move motors
          if (DEBUG_MOTOR) {
            Serial.print("MoveStart ");
            Serial.print(millis() - interval_tm);
            Serial.print(";");
          }
          move_motors();
          if (DEBUG_MOTOR) {
            Serial.print("Moveend ");
            Serial.print(millis() - interval_tm);
            Serial.print(";");
          }

          //Turn off the motors if we have selected powersave 3 and 4 are the only ones we want here
          if (POWERSAVE_PT > 2) disable_PT();
          if (POWERSAVE_AUX > 2) disable_AUX();  //


          //Update display
          if (intval != 3) display_status();  //update after shot complete to avoid issues with pausing


          Shot_Sequence_Engaged = false;  //Shot sequence engaged flag is is off - we are ready for our next
          Interrupt_Fire_Engaged = false;
          //CZ_Button_Read_Count=0;
          //InterruptAction_Reset(); //enable the external interrupts to start a new shot
          if (DEBUG) { Serial.println("EOL"); }
        }

        if (camera_moving_shots > 0 && camera_fired >= camera_total_shots) {  //end of program
          lcd.empty();
          draw(58, 1, 1);  //lcd.at(1,1,"Program Complete");
          Program_Engaged = false;
          if (POWERSAVE_PT > 1) disable_PT();    //  low, standard, high, we power down at the end of program
          if (POWERSAVE_AUX > 1) disable_AUX();  // low, standard, high, we power down at the end of program
          delay(prompt_time * 2);
          progstep = 90;
          first_time = 1;
        }

        //This portion always runs in empty space of loop.

        NunChuckQuerywithEC();
        NunChuckjoybuttons();
        Check_Prog();  //look for button presses
        //if (CZ_Button_Read_Count>10 && intval==EXTTRIG_INTVAL ) Interrupt_Fire_Engaged=true; // manual trigger
        //if (PAUSE_ENABLED && CZ_Button_Read_Count>10 && intval>3 && !Shot_Sequence_Engaged ) Pause_Prog(); //pause an SMS program
        if (PAUSE_ENABLED && CZ_Button_Read_Count > 25 && intval > 3 && !Shot_Sequence_Engaged && CZ_Released) SMS_In_Shoot_Paused_Menu();  //jump into shooting menu


        break;  //break 50




      case 51:

        //main video loop interrupt based.  This runs for 2 point moves only.

        if (progtype == REG2POINTMOVE || progtype == REV2POINTMOVE) {
          synched3AxisMove_timed(motor_steps_pt[2][0], motor_steps_pt[2][1], motor_steps_pt[2][2], float(overaldur), float(rampval / 100.0));
          if (maxVelLimit) {  //indicates the move is limited to enforce velocity limit on motors)
            lcd.at(2, 1, "Speed Limit");
          }
          //Start us moving
          // interval_tm_last=interval_tm;
          interval_tm = millis();

          startISR1();
          do {
            if (!nextMoveLoaded) {
              updateMotorVelocities();
            }
          } while (motorMoving);

          stopISR1();

          Serial.print("Video Runtime");
          Serial.println(millis() - interval_tm);





          if (!motorMoving && (sequence_repeat_type == 0)) {  //new end condition for RUN CONTINOUS
            boolean break_continuous = false;
            lcd.empty();
            draw(58, 1, 1);  //lcd.at(1,1,"Program Complete");
            Program_Engaged = false;
            for (int i = 0; i < 30; i++) {
              NunChuckQuerywithEC();
              NunChuckjoybuttons();
              Check_Prog();  //look for button presses
              if (PAUSE_ENABLED && CZ_Button_Read_Count > 25) {
                break_continuous = true;
                lcd.empty();
                lcd.at(1, 1, "Stopping Run");
                lcd.at(2, 1, "Release Buttons");
                do {
                  NunChuckQuerywithEC();
                  NunChuckjoybuttons();

                } while (c_button || z_button);
                progstep = 9;
              }
            }

            //add section to delay here if the delay is set.
            while (start_delay_tm > millis() / 1000L) {
              //enter delay routine
              calc_time_remain_start_delay();
              if ((millis() - diplay_last_tm) > 1000) display_time(2, 1);
              NunChuckQuerywithEC();
              NunChuckjoybuttons();
              Check_Prog();  //look for long button press
                             //if (CZ_Button_Read_Count>20 && !Program_Engaged) {
                             //	start_delay_tm=((millis()/1000L)+5); //start right away by lowering this to 5 seconds.
                             //	CZ_Button_Read_Count=0; //reset this to zero to start
                             //}
            }

            //end start delay


            if (!break_continuous) Auto_Repeat_Video();  //only run this if there isn't a break command
            first_time = 1;
          } else if (!motorMoving && (sequence_repeat_type == 1)) {  //new end condition for RUN ONCE
            lcd.empty();
            draw(58, 1, 1);  //lcd.at(1,1,"Program Complete");
            Program_Engaged = false;
            if (POWERSAVE_PT > 1) disable_PT();    //  low, standard, high, we power down at the end of program
            if (POWERSAVE_AUX > 1) disable_AUX();  // low, standard, high, we power down at the end of program
            progstep = 90;
            first_time = 1;
            delay(100);
            //NunChuckQuerywithEC();
          }



        }  // end interrupt routine driven for 2 points

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

        //Start video loop for 3 Point moves - this loop does not use the new motor move profile as it needs to calculate each and every segment
        if (progtype == REG3POINTMOVE || progtype == REV3POINTMOVE) {  //this is regular 3 point move program that can be modified later
          if (DEBUG) {
            interval_tm_last = interval_tm;
            interval_tm = millis();
          }
          //Start us moving

          if (DEBUG) {
            Serial.print("trueinterval ");
            Serial.print(interval_tm - interval_tm_last);
            Serial.print(";");
          }

          if (DEBUG_MOTOR) {
            Serial.print("MoveStart ");
            Serial.print(millis());
            Serial.print(";");
          }

          camera_fired++;  //still need this for framing
          move_motors();

          if (DEBUG_MOTOR) {
            Serial.print("Moveend ");
            Serial.println(millis());
          }


          if (camera_total_shots > 0 && camera_fired >= camera_total_shots) {
            lcd.empty();
            //draw(58,1,1);//lcd.at(1,1,"Program Complete");
            Program_Engaged = false;
            if (POWERSAVE_PT > 1) disable_PT();    //  low, standard, high, we power down at the end of program
            if (POWERSAVE_AUX > 1) disable_AUX();  // low, standard, high, we power down at the end of program
            delay(prompt_time * 2);
            progstep = 90;
            first_time = 1;
            //delay(100);
            //NunChuckQuerywithEC();
          }

        }  // End video loop for 3 Point moves


        break;  //break 51 - VIDEO



      case 52:  // loop for external interrupt - external triggering

        //New interrupt Flag Checks

        if (changehappened) {
          changehappened = false;
          if (!state)  //start the clock as the cam shutter witch closed and sense pin, was brought low
          {
            ext_shutter_open = true;
            shuttertimer_open = micros();
            if (DEBUG) Serial.print("shuttertimer_a=");
            Serial.print(shuttertimer_open);

          } else if (state)  //shutter closed - sense pin goes back high - stop the clock and report
          {
            ext_shutter_open = false;
            shuttertimer_close = micros();  //turn on the led / shutter
            ext_shutter_count++;
            if (DEBUG) Serial.print(" ext_shutter_count=");
            Serial.print(ext_shutter_count);
            if (DEBUG) Serial.print(" shuttertimer_b=");
            Serial.print(shuttertimer_close);
            Serial.print("diff=");
            Serial.println(shuttertimer_close - shuttertimer_open);
          }
        }
        //end interrupt check and flagging


        //  Start of states for external shooting loop

        if ((Program_Engaged) && !(Shot_Sequence_Engaged) && !(Shutter_Signal_Engaged) && (ext_shutter_open)) {  //start a shot sequence flag

          Shot_Sequence_Engaged = true;  //
        }


        if ((Program_Engaged) && (Shot_Sequence_Engaged) && !(Shutter_Signal_Engaged) && (ext_shutter_open)) {  //fire the camera can happen more than once in a shot sequence with HDR

          if (DEBUG) {
            Serial.print("Startshot_at:");
            Serial.print(millis());
            Serial.println(";");
          }

          //Fire Camera
          //don't fire the camera with the timer, just turn on our focus and shutter pins - we will turn them off when we sense the shot is done.
          digitalWrite(FOCUS_PIN, HIGH);
          digitalWrite(CAMERA_PIN, HIGH);
          Shutter_Signal_Engaged = true;
          //camera_fired++;
        }


        if (Shot_Sequence_Engaged && (Shutter_Signal_Engaged) && !(ext_shutter_open)) {  //shutter just closed, stop the camera port and move

          digitalWrite(FOCUS_PIN, LOW);
          digitalWrite(CAMERA_PIN, LOW);
          Shutter_Signal_Engaged = false;


          if (ext_shutter_count >= ext_hdr_shots) {  //this is future functionality  - leave at 1 for now

            camera_fired++;
            ext_shutter_count = 0;
            //Move the motors - each motor move is calculated by where we are in the sequence - we still call this for lead in and lead out - motors just don't move

            Move_Engaged = true;  //move motors
            if (DEBUG_MOTOR) {
              Serial.print("MoveStart ");
              Serial.print(millis() - interval_tm);
              Serial.print(";");
            }
            move_motors();
            if (DEBUG_MOTOR) {
              Serial.print("Moveend ");
              Serial.print(millis() - interval_tm);
              Serial.print(";");
            }

            //Turn off the motors if we have selected powersave 3 and 4 are the only ones we want here
            if (POWERSAVE_PT > 2) disable_PT();
            if (POWERSAVE_AUX > 2) disable_AUX();  //


            //Update display
            display_status();  //update after shot complete to avoid issues with pausing

            Shot_Sequence_Engaged = false;  //Shot sequence engaged flag is is off - we are ready for our next
            CZ_Button_Read_Count = 0;
            //InterruptAction_Reset(); //enable the external interrupts to start a new shot
            if (DEBUG) { Serial.println("EOL"); }
          }
        }

        if (camera_moving_shots > 0 && camera_fired >= camera_total_shots) {  //end of program
          lcd.empty();
          draw(58, 1, 1);  //lcd.at(1,1,"Program Complete");
          Program_Engaged = false;
          if (POWERSAVE_PT > 1) disable_PT();    //  low, standard, high, we power down at the end of program
          if (POWERSAVE_AUX > 1) disable_AUX();  // low, standard, high, we power down at the end of program
          delay(prompt_time * 2);
          progstep = 90;
          first_time = 1;
        }
        NunChuckQuerywithEC();
        NunChuckjoybuttons();
        Check_Prog();                                                                              //look for button presses
        if (CZ_Button_Read_Count > 10 && intval == EXTTRIG_INTVAL) Interrupt_Fire_Engaged = true;  // manual trigger
                                                                                                   //if (PAUSE_ENABLED && CZ_Button_Read_Count>20 && intval>3 && !Shot_Sequence_Engaged ) Pause_Prog(); //pause an SMS program

        break;  //break 52 - end external triggering loop



      case 90:  // end of program - offer repeat and reverse options - check the nuncuck
        if (first_time == 1) {
          lcd.empty();
          lcd.at(1, 4, "Repeat - C");
          lcd.at(2, 4, "Reverse - Z");
          NunChuckQuerywithEC();
          first_time = 0;
          delay(100);
        }

        //This portion always runs in empty space of loop.

        NunChuckQuerywithEC();
        NunChuckjoybuttons();
        Check_Prog();  //look for button presses
        //add error handling here to prevent accidental starts
        //if (CZ_Button_Read_Count>25  && CZ_Released ) button_actions_end_of_program();  //Repeat or Reverses
        button_actions_end_of_program();
        //delay(1); //don't just hammer on this - query at regular interval

        break;  // break 90

      case 250:  // loop for Pano

        //Kick off the shot sequence!!!  This happens once per camera shot.
        if ((intval > 2) && (Program_Engaged) && !(Shot_Sequence_Engaged) && ((millis() - interval_tm) > interval)) {
          interval_tm_last = interval_tm;  //just used for shot timing comparison

          interval_tm = millis();  //start the clock on our shot sequence
          if (DEBUG) {
            Serial.print("trueinterval: ");
            Serial.print(interval_tm - interval_tm_last);
            Serial.print(";");
          }
          Interrupt_Fire_Engaged = false;  //clear this flag to avoid re-entering this routine

          Shot_Sequence_Engaged = true;   //
          Prefire_Engaged = true;         //
          IO_Engaged = true;              //
          digitalWrite(FOCUS_PIN, HIGH);  //for longer shot interval, wake up the camera

          //if (POWERSAVE_PT<4)   enable_PT();  //don't power on for shot for high power saving
          //if (AUX_ON && POWERSAVE_AUX<4)   enable_AUX();  //don't power on for shot for high power saving
          enable_PT();
        }



        //End our prefire - check that we are in program active,shot cycle engaged, and prefire engaged and check against our prefire time
        //If so set prefire flag off, static flag on, fire camera for static time value, update the display

        if ((Shot_Sequence_Engaged) && (Prefire_Engaged) && ((millis() - interval_tm) > prefire_time * 100)) {

          Prefire_Engaged = false;
          if (DEBUG) {
            Serial.print("PreDoneAt ");
            Serial.print(millis() - interval_tm);
            Serial.print(";");
          }

          Static_Time_Engaged = true;
          //Fire Camera
          fire_camera((long)static_tm * 100);  //start shutter sequence
          camera_fired++;
        }

        //End out static time - check that we are in an program active and static time,  Shutter not engaged, check shot cycle time against prefire+statictime
        //If so remove flags from Static Time Engaged and IO engaged, Turn off I/O port, set flags for motors moving, move motors
        //move motors - figure out delays.   Long delays mean really slow - choose the minimum of the calculated or a good feedrate that is slow

        //if (Program_Engaged && Shot_Sequence_Engaged && Static_Time_Engaged && !Shutter_Signal_Engaged && ((millis() - interval_tm) > (prefire_time*100+static_tm*100)) ) {
        if (Shot_Sequence_Engaged && Static_Time_Engaged && !Shutter_Signal_Engaged && ((millis() - interval_tm) > (prefire_time * 100 + static_tm * 100))) {  //removed requirement for Program Engaged for external interrupt


          Static_Time_Engaged = false;  //Static Time Engaged is OFF
          IO_Engaged = false;           //IO Engaged is off
          //digitalWrite(IO_2, LOW); //Use this as the iterrupt
          //digitalWrite(IO_3, LOW);  //Turn off Pin 3
          //Serial.print("IO3_off"); //Serial.println(millis()-interval_tm);


          //Move the motors - each motor move is calculated by where we are in the sequence - we still call this for lead in and lead out - motors just don't move

          Move_Engaged = true;  //move motors
          if (DEBUG_MOTOR) {
            Serial.print("MoveStart ");
            Serial.print(millis() - interval_tm);
            Serial.print(";");
          }
          if (DEBUG_PANO) Serial.print("progtype ");
          Serial.println(progtype);
          if (progtype == PANOGIGA)  //regular pano
          {
            if (P2PType == 0) {
              move_motors_pano_basic();
            } else if (P2PType == 1) {
              move_motors_pano_accel();
            }
          }

          else if (progtype == PORTRAITPANO)  //PORTRAITPANO method array load
          {
            if (DEBUG_PANO) Serial.print("entered PORTRAITPANO loop");
            move_motors_accel_array();
            delay(PanoPostMoveDelay);
          }





          //
          if (DEBUG_MOTOR) {
            Serial.print("Moveend ");
            Serial.print(millis() - interval_tm);
            Serial.print(";");
          }

          //Turn off the motors if we have selected powersave 3 and 4 are the only ones we want here
          //if (POWERSAVE_PT>2)   disable_PT();
          //if (POWERSAVE_AUX>2)   disable_AUX();  //

          //


          if (P2PType == 0) {
            Serial.println("finished basic move");
            if (intval != 3) display_status();  //update after shot complete to avoid issues with pausing
            Move_Engaged = false;
            Shot_Sequence_Engaged = false;  //Shot sequence engaged flag is is off - we are ready for our next
            Interrupt_Fire_Engaged = false;
            CZ_Button_Read_Count = 0;
            //InterruptAction_Reset(); //enable the external interrupts to start a new shot
            if (DEBUG) {
              Serial.println("EOL");
            }
          }

        }  //end test

        //just have this repeat like we are in loop
        if (P2PType == 1)  //acceleration profiles
        {

          if (!nextMoveLoaded) {
            updateMotorVelocities();  //finished up the interrupt routine
                                      //Print_Motor_Params(2);
          }

          //test for completed move
          if (Shot_Sequence_Engaged && Move_Engaged && motorMoving == 0)  //motors completed the move
          {
            Serial.println("finished accel move");
            if (intval != 3) display_status();  //update after shot complete to avoid issues with pausing
            Move_Engaged = false;
            Shot_Sequence_Engaged = false;  //Shot sequence engaged flag is is off - we are ready for our next
            Interrupt_Fire_Engaged = false;
            CZ_Button_Read_Count = 0;
            //InterruptAction_Reset(); //enable the external interrupts to start a new shot
            if (DEBUG) {
              Serial.println("EOL");
            }
          }
        }



        if (camera_moving_shots > 0 && camera_fired >= camera_total_shots) {  //end of program
          lcd.empty();
          draw(58, 1, 1);  //lcd.at(1,1,"Program Complete");
          Program_Engaged = false;
          if (POWERSAVE_PT > 1) disable_PT();    //  low, standard, high, we power down at the end of program
          if (POWERSAVE_AUX > 1) disable_AUX();  // low, standard, high, we power down at the end of program
          delay(2000);
          progstep = 290;
          first_time = 1;
        }
        //updateMotorVelocities();  //uncomment this for DF Loop
        NunChuckQuerywithEC();
        NunChuckjoybuttons();
        //Check_Prog(); //look for button presses
        // if (CZ_Button_Read_Count>10 && intval==EXTTRIG_INTVAL ) Interrupt_Fire_Engaged=true; // manual trigger
        // if (PAUSE_ENABLED && CZ_Button_Read_Count>20 && intval>3 && !Shot_Sequence_Engaged ) Pause_Prog(); //pause an SMS program

        break;  //break 250


      case 290:  //  finished up pano
        if (first_time == 1) {
          lcd.empty();
          stopISR1();
          draw(58, 1, 1);  //lcd.at(1,1,"Program Complete");
          draw(59, 2, 1);  //lcd.at(2,1," Repeat Press C");
          NunChuckQuerywithEC();
          first_time = 0;
          delay(100);
        }
        NunChuckQuerywithEC();
        NunChuckjoybuttons();
        button_actions290();  //read buttons, look for c button press to start run
        break;                // break 90


    }  //switch
  }    // while
}  //loop

Thanks in adavance.

Most members (myself included) are very wary of downloading and unzipping files from an unknown source. Please read the forum guidelines to see how to properly post code and some information on making a good post.

Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

Please post a wiring diagram showing how the project should be wired.

Please post clear photos showing how the project is wired.

The more information that we have, the faster and better the help can be.

Sorry I was in a hurry this morning and didn't realize the file was still in a zipped folder. Hopefully it is all good now.

What Arduino board are you using?

Awaiting that wiring diagram.

Wiring diagram uploaded for Arduino Mega

The NHD-0216K3Z-FL-GBW display uses a specific library that will not work with a standard 16x2 LCD.

You will need to swap out all the code that references the old display with alternative code. You'll need to find the equivalent functions for these methods...

lcd.setup()
lcd.contrast()
lcd.cursorOff()
lcd.bright()
lcd.empty()
lcd.at()

I suggest using this library...

There are lots of example programs that come with it.

+1 for the hd44780 library that was recommended by @red_car.

The class in the hd44780 library that is appropriate for the I2C capable LCD pictured in the OP is the hd44780_I2Cexp class. The library is available to install via the IDE library manager.

In the examples, there is a diagnostic sketch that will help us to help you if you still have trouble with the display. Run the diagnostic sketch and post the results.

What with this. And there are more places.

The display is an I2C/SPI/RS232 (TTL) one. NewHaven has more of them. All the NHD-0216K3Z.... are compatible. All of them has a PIC16F690 as sub controller for the HD44780/ST7066 (datasheet)

Ground and +5V are clearly. LCD is likely the RS232 use. That is the only one with 3 wire connection.

Is this the one. I have installed it and do I just now upload this to the Mega board.

Screenshot 2022-12-31 140557

No, that is not the library that I recommend. That is an older library that is for parallel interface LCDs, nor I2C.

To install the hd44780 library. The hd44780 library is the best available for I2C LCDs. The library is available in the Library Manager. Go to Library Manager (in the IDE menus, Sketch, Include Libraries, Manage Libraries) and in the Topics dropdown choose "Display" and in the "Filter Your Search" box enter hd44780. Select and install the hd44780 library by Bill Perry.

The class that you want to use is the hd44780_I2Cexp class. There are examples to show how to use the library. The nice thing about the hd44780 library is that it will autodetect the I2C address and the I2C backpack to LCD pin mapping.

Hi, @beretta

Does anything appear on the display?
Have you adjusted the contrast potentiometer on the I2C backboard?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

Ok found it and installed it. Now do I upload to the Mega

If its properly installed, use an example code that comes with the library, it will do it all.

Can you please tell us your electronics, programming, arduino, hardware experience?

Tom... :smiley: :+1: :coffee: :australia:

Ok Thanks I will try it now. Fingers crossed. My experience with arduino , programming is about 2 hours now. Previously zero.

Just got this error .

TB3_Black_109_Release1\WiiNunchuck3.cpp:13:10: fatal error: ../Wire/Wire.h: No such file or directory
#include "../Wire/Wire.h"
^~~~~~~~~~~~~~~~
compilation terminated.

exit status 1

Compilation error: ../Wire/Wire.h: No such file or directory

Hi,
Can you please post the example code?
To add code please click this link;

Thanks... Tom.. :smiley: :+1: :coffee: :australia:

Hi
This is the code after installing the hd44780 libray

/*

(c) 2015 Brian Burling eMotimo INC


    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.



*/

/*


    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
111 Target - Aux Distance with ability for continuous loop - shorten lean.
Add Stopmotion to Inshot menu
Add Brightness to in shot menu

109 Release Notes

-Fixed Aux reverse to work in all cases
-Added ability to reverse AUX_REV to EEPROM direction.
-Added interval change functionality to in shot menu - don't recommend this is used ever unless your shot is already ruined.  Changing anything mid shot will show.
-Added functionality to use left right to set frame to go to.  Can go forward or back.
-Relaxed tight requirements for joystick absolute centering - check
-Fixed motor feedrate issue when Static Time was maxed out.  If you are maxing out your static time by default, you are not using this setting correctly and hurting your shot!  
-Made Static time a max of Interval minus 0.3 seconds to allow at least a .15 second move - check
-Added abs on feedrate min calc to accommodate spurious overrun negatives on SMS shoots resulting in single long frame delays
-Added check on minimum for video to ensure we don't catch 3PT video moves on min calc.
-Added test against power policy for loop 52 (ext triggering)  
-Added ramping and new motor move to starts and ends (decoupled inputs)
-Added coordinated return to start and three axis moves.
-Updated the motorMoving to accurately assign this
-Broke up move profiles.  Added slow down routine to the move to start/move to end.
-Throttled the calc of the move to respect max jog speeds by axis.  If we hit this we indicates "Speed Limit" on video run screen.  If you hit this, lengthen move and/or decrease ramp
-Added to the Setup Menu the Motor Speed parameter - from 2000 to 20000 max to allow folks to tune.the speeds for AUX.  Pan and Tilt are hardcoded.
-Start delay cleaned up and fixed - now down to the second - also a bailout of CZ to get to 5 seconds so you aren't stuck with accidental long delays
-Add Going to End LCD prompt if heading there.
-Target, Go To End. This now works
-Focus on return to start method.  Pause parameters improved to prevent toggling - added CZ released to check for long holds and released.
-Added new Tab for TB3_InShootMenu - just pauses now and only from progstep 50 (regular SMS)
-Added return to start - just called the same routine from the repeat move at the end of the shot - finds start fine (0's) not sure
*/ 

/* 

 =========================================
Main Program
 =========================================
 
*/

#include <Wire.h>
#include <SoftwareSerial.h> 
#include <EEPROM.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "WiiNunchuck3.h"
#include "NHDLCD9.h"

NHDLCD9 lcd(4,2,16); // desired pin, rows, cols   //BB for LCD

char lcdbuffer1[20]; //this used to be 16, but increased to 20 do to overflow when we moved to Arduino 1.6 (stalled and failed)

const char setup_0[] PROGMEM = "Setup Complete";   
const char setup_1[] PROGMEM = "    TB3_109";  
const char setup_2[] PROGMEM = "Connect Joystick";
const char setup_3[] PROGMEM = "C-Next Z-Go Back";
const char setup_4[] PROGMEM = "C-Use Stored";
const char setup_5[] PROGMEM = "Z-Reset";
const char setup_6[] PROGMEM = "Params Reset";
const char setup_7[] PROGMEM = "Low Power"; 
const char setup_8[] PROGMEM = "Move to Start Pt";
const char setup_9[] PROGMEM = "Start Pt. Set";
const char setup_10[] PROGMEM = "Move to Point"; 
const char setup_11[] PROGMEM = "Moving to stored";
const char setup_12[] PROGMEM = "end point";
const char setup_13[] PROGMEM = "Confirm or Move";
const char setup_14[] PROGMEM = "C-Next";
const char setup_15[] PROGMEM = "Move to End Pt.";
const char setup_16[] PROGMEM = "End Point Set";
const char setup_17[] PROGMEM = "Set Sht Interval";
const char setup_18[] PROGMEM = "Intval:   .  sec";
const char setup_19[] PROGMEM = " Ext.Trig";
const char setup_20[] PROGMEM = " Video   ";
const char setup_21[] PROGMEM = "Interval Set";
const char setup_22[] PROGMEM = "Set Static Time";
const char setup_23[] PROGMEM = "Stat_T:   .  sec";
const char setup_24[] PROGMEM = " Video   ";
const char setup_25[] PROGMEM = "Static Time Set";
const char setup_26[] PROGMEM = "Set PreFire Time";
const char setup_27[] PROGMEM = " Pre_T:   .  sec";
const char setup_28[] PROGMEM = "Prefire Time Set";
const char setup_29[] PROGMEM = "    Set Ramp";
const char setup_30[] PROGMEM = "Ramp:     Frames";
const char setup_31[] PROGMEM = "Ramp Set";
const char setup_32[] PROGMEM = "Set Move";
const char setup_33[] PROGMEM = "Duration";
const char setup_34[] PROGMEM = "H:MM:SS";
const char setup_35[] PROGMEM = "Duration Set";
const char setup_36[] PROGMEM = "Set Static Lead";
const char setup_37[] PROGMEM = "In/Out Frames";
const char setup_38[] PROGMEM = "In      Out";
const char setup_39[] PROGMEM = "Lead Frames Set";
const char setup_40[] PROGMEM = " Going to Start";
const char setup_41[] PROGMEM = "Review and";
const char setup_42[] PROGMEM = "Confirm Setting";
const char setup_43[] PROGMEM = "Pan Steps:";
const char setup_44[] PROGMEM = "Tilt Steps:";
const char setup_45[] PROGMEM = "Cam Shots:";
const char setup_46[] PROGMEM = "Time:";
const char setup_47[] PROGMEM = "Ready?";
const char setup_48[] PROGMEM = "Press C Button";
const char setup_49[] PROGMEM = "Program Running";
const char setup_50[] PROGMEM = "Waiting for Ext.";
const char setup_51[] PROGMEM = "LeadIn";
const char setup_52[] PROGMEM = "RampUp";
const char setup_53[] PROGMEM = "Linear";
const char setup_54[] PROGMEM = "RampDn";
const char setup_55[] PROGMEM = "LeadOT";
const char setup_56[] PROGMEM = "Finish";
const char setup_57[] PROGMEM = "Center Joystick";
const char setup_58[] PROGMEM = "Program Complete";
const char setup_59[] PROGMEM = " Repeat Press C";
const char setup_60[] PROGMEM = "Battery too low";
const char setup_61[] PROGMEM = "  to continue";
const char setup_62[] PROGMEM = "Pause ";
const char setup_63[] PROGMEM = "Point X Set";
const char setup_64[] PROGMEM = "Using Set Params";
const char setup_65[] PROGMEM = "UpDown  C-Select";
const char setup_66[] PROGMEM = "New   Point Move";
const char setup_67[] PROGMEM = "Enabled";
const char setup_68[] PROGMEM = "Disabled";
const char setup_69[] PROGMEM = "PowerSave";
const char setup_70[] PROGMEM = "Always";
const char setup_71[] PROGMEM = "Program";
const char setup_72[] PROGMEM = "Shoot (accuracy)";
const char setup_73[] PROGMEM = "Shoot (pwr save)";
const char setup_74[] PROGMEM = "Aux Motor:";
const char setup_75[] PROGMEM = "Set Angle o'View";
const char setup_76[] PROGMEM = "C-Set, Z-Reset";
const char setup_77[] PROGMEM = "Pan AOV: ";
const char setup_78[] PROGMEM = "Tilt AOV: ";
const char setup_79[] PROGMEM = "   % Overlap";
const char setup_80[] PROGMEM = "Overlap Set";
const char setup_81[] PROGMEM = "Rev   Point Move";
const char setup_82[] PROGMEM = "DF Slave Mode";
const char setup_83[] PROGMEM = "Setup Menu"; //not sure why this fails
const char setup_84[] PROGMEM = "Panorama";
const char setup_85[] PROGMEM = "AuxDistance";
const char setup_86[] PROGMEM = "Resume";
const char setup_87[] PROGMEM = "Restart";
const char setup_88[] PROGMEM = "Go to Frame";
const char setup_89[] PROGMEM = "Go to End";
const char setup_90[] PROGMEM = "90";



//PROGMEM const char *setup_str[] = {setup_0,setup_1,setup_2,setup_3,setup_4,setup_5,setup_6,setup_7,setup_8,setup_9,setup_10,
PGM_P const setup_str[] PROGMEM ={setup_0,setup_1,setup_2,setup_3,setup_4,setup_5,setup_6,setup_7,setup_8,setup_9,setup_10,	
setup_11,setup_12,setup_13,setup_14,setup_15,setup_16,setup_17,setup_18,setup_19,setup_20,
setup_21,setup_22,setup_23,setup_24,setup_25,setup_26,setup_27,setup_28,setup_29,setup_30,
setup_31,setup_32,setup_33,setup_34,setup_35,setup_36,setup_37,setup_38,setup_39,setup_40,
setup_41,setup_42,setup_43,setup_44,setup_45,setup_46,setup_47,setup_48,setup_49,setup_50,
setup_51,setup_52,setup_53,setup_54,setup_55,setup_56,setup_57,setup_58,setup_59,setup_60,
setup_61,setup_62,setup_63,setup_64,setup_65,setup_66,setup_67,setup_68,setup_69,setup_70,
setup_71,setup_72,setup_73,setup_74,setup_75,setup_76,setup_77,setup_78,setup_79,setup_80,
setup_81,setup_82,setup_83,setup_84,setup_85,setup_86,setup_87,setup_88,setup_89,setup_90};


//Global Parameters 
#define DEBUG 0//
#define DEBUG_MOTOR 0//
#define DEBUG_NC 0 //
#define DEBUG_PANO 0
#define DEBUG_GOTO 0
#define POWERDOWN_LV false //set this to cause the TB3 to power down below 10 volts
#define MAX_MOVE_POINTS 3
#define VIDEO_FEEDRATE_NUMERATOR 375L // Set this for 42000L, or 375L for faster calc moves
#define PAN_MAX_JOG_STEPS_PER_SEC 10000.0
#define TILT_MAX_JOG_STEPS_PER_SEC 10000.0
//#define AUX_MAX_JOG_STEPS_PER_SEC 15000.0 //this is defined in the setup menu now.


//Main Menu Ordering

#define MENU_OPTIONS  8


#define REG2POINTMOVE 0
#define REV2POINTMOVE 1
#define REG3POINTMOVE 2
#define REV3POINTMOVE 3
#define PANOGIGA      4
#define PORTRAITPANO  5
#define DFSLAVE       6
#define SETUPMENU     7
#define AUXDISTANCE   99



//Portrait Pano
#define PanoArrayTypeOptions 5

#define PANO_9ShotCenter	1
#define PANO_25ShotCenter	3
#define PANO_7X3			2
#define PANO_9X5Type1		6
#define PANO_9X5Type2		7
#define PANO_5x5TopThird	4
#define PANO_7X5TopThird	5

//In Program Menu Ordering
#define INPROG_OPTIONS  5    //up this when code for gotoframe

#define INPROG_RESUME       0
#define INPROG_RTS          1 //return to start
#define INPROG_GOTO_END     2 //Go to end
#define INPROG_GOTO_FRAME   3 //go to frame
#define INPROG_INTERVAL     4 //Set Interval
#define INPROG_STOPMOTION   99 //Manual Forward and Back

//Interval Options
#define VIDEO_INTVAL  2
#define EXTTRIG_INTVAL 3
#define MIN_INTERVAL_STATIC_GAP 3  //min gap between interval and static time
//#define STOPMOT //not used

//TB3 section - Black or Orange Port Mapping for Step pins on Stepper Page
#define MOTORS 3
#define MOTOR0_STEP  5 
#define MOTOR1_STEP  6 
#define MOTOR2_STEP  7
#define MOTOR0_DIR   8 
#define MOTOR1_DIR   9 
#define MOTOR2_DIR   10
#define MOTOR_EN  A3
#define MOTOR_EN2  11
#define MS1 A1 
#define MS2 A2 
#define MS3 A2
#define IO_2  2 // drives middle of 2.5 mm connector on I/O port
#define IO_3  3 // drives tip of 2.5 mm connector on I/O port
#define CAMERA_PIN  12 // drives tip of 2.5 mm connector
#define FOCUS_PIN   13 // drives  middle of 2.5mm connector
#define STEPS_PER_DEG  444.444 //160000 MS per 360 degees = 444.4444444

/*
STEPS_PER_INCH_AUX for various motors with 17 tooth final gear on 5mm pitch belt
Phidgets 99:1	95153
Phidgets 27:1	25676
Phidgets 5:1	4955
20:1 Ratio	19125
10:1 Ratio	9562
*/

#define STEPS_PER_INCH_AUX 19125 //
#define MAX_AUX_MOVE_DISTANCE 311 //(31.1 inches)
//end TB3 section

unsigned long build_version=10951; //this value is compared against what is stored in EEPROM and resets EEPROM and setup values if it doesn't match
unsigned int  intval=2; //seconds x10  - used for the interval prompt and display
unsigned long interval = 2000; //calculated and is in ms
unsigned int  camera_fired     = 0; //number of shots fired
unsigned int  camera_moving_shots = 200; //frames for new duration/frames prompt
unsigned int  camera_total_shots= 0; //used at the end target for camera fired to compare against
unsigned int  overaldur=20; //seconds now for video only
unsigned int  prefire_time = 1; //currently hardcoded here to .1 second - this powers up motor early for the shot
unsigned int  rampval=50;
unsigned int  static_tm=1; //new variable
unsigned int  lead_in=1;
unsigned int  lead_out=1;
unsigned int  start_delay_sec=0;
int aux_dist;

//External Interrupt Variables
volatile int state = 0; //new variable for interrupt
volatile boolean changehappened=false;  //new variable for interrupt
long shuttertimer_open=0;
long shuttertimer_close=0;
boolean ext_shutter_open = false;
int ext_shutter_count = 0;
int ext_hdr_shots = 1; //this is how many shots are needed before moving - leave at one for normal shooting - future functionality with external 

//Start of variables for Pano Mode
unsigned int P2PType=1;  // 0 = no accel, 1= accel
unsigned int PanoPostMoveDelay=200;

//3 Point motor routine values
float motor_steps_pt[MAX_MOVE_POINTS][MOTORS];  // 3 total points.   Start point is always 0.0
float percent; //% through a leg 
unsigned int keyframe[2][6]= {{0,0,0,0,0,0},{0,0,0,0,0,0}}; //this is basically the keyframes {start, end of rampup, start or rampdown, end}   - doesn't vary by motor at this point
float linear_steps_per_shot [MOTORS] = {0.0,0.0,0.0}; //{This is for the calculated or estimated steps per shot in a segment for each motor
float ramp_params_steps [MOTORS] = {0.0,0.0,0.0}; //This is to calc the steps at the end of rampup for each motor.  Each array value is for a motor

//Program Status Flags
boolean Program_Engaged=false;
boolean Shot_Sequence_Engaged=false;
boolean Prefire_Engaged=false;
boolean Shutter_Signal_Engaged=false;
boolean Static_Time_Engaged=false;
boolean IO_Engaged=false;
boolean Move_Engaged=false;
boolean Interrupt_Fire_Engaged=false;

//Timer2flags
unsigned long MsTimer2_msecs;
//void (*MsTimer2_func)();
volatile unsigned long MsTimer2_count;
volatile char MsTimer2_overflowing;
volatile unsigned int MsTimer2_tcnt2;

//New Powersave flags
/*Power Save explanation
We can power up and power down the Pan Tilt motors together.  We can power up and power down the Aux motor port as well.  We see three levels of power saving:
1)  None - Motors are always on - for VFX work where power isn't a factor and precision is most important.  Motors will get warm here on hot days.
2)  Low - only at the end of program 
3)  Standard - Power up the motors for the shooting time (all the time we hold the trigger down), and move, power down between shots.
4)  High - Only power on for motor moves, turn off the motors when we reach the shooting position.  
    We are powered down for the shot and only power on for moves. This saves a ton of battery for long astro shots.   
    We do lose microstep resolution for this, but it usually is not visible.   We could be off by as much as 8/16 mircosetps for a shot or 0.018 degrees - Really small stuff!  Try this mode out!
*/


//CVariables that are set during the Setup Menu store these in EEPROM
unsigned int  POWERSAVE_PT;  //1=None - always on  2 - low   3=standard    4=High
unsigned int  POWERSAVE_AUX;  //1=None - always on  2 - low   3=standard    4=High
byte AUX_ON;  //1=Aux Enabled, 2=Aux disabled
byte PAUSE_ENABLED;  //1=Pause Enabled, 0=Pause disabled
boolean REVERSE_PROG_ORDER; //Program ordering 0=normal, start point first. 1=reversed, set end point first to avoid long return to start
boolean MOVE_REVERSED_FOR_RUN=0;
unsigned int  LCD_BRIGHTNESS_DURING_RUN;  //0 is off 8 is max
unsigned int  AUX_MAX_JOG_STEPS_PER_SEC; //value x 1000  20 is the top or 20000 steps per second.
byte AUX_REV;  //1=Aux Enabled, 2=Aux disabled


//control variable, no need to store in EEPROM - default and setup during shot
unsigned int progstep = 0; //used to define case for main loop
boolean progstep_forward_dir=true; //boolean to define direction of menu travel to allow for easy skipping of menus
unsigned int progtype=0; //updownmenu selection
int inprogtype=0; //updownmenu selection during shoot
boolean reset_prog=1; //used to handle program reset or used stored
unsigned int first_time=1; //variable to help with LCD dispay variable that need to show one time
boolean first_time2=true;
int batt_low_cnt=0;
unsigned int max_shutter;
unsigned int max_prefire;
unsigned int program_progress_2PT=1;  //Lead in, ramp, linear, etc for motor routine case statement
unsigned int program_progress_3PT=1;  //phase 1, phase 2
unsigned long interval_tm        = 0;  //mc time to help with interval comparison
unsigned long interval_tm_last =0; //mc time to help with interval comparison
int cursorpos=1; //use 1 for left, 2 for right  - used for lead in, lead out
unsigned int lcd_dim_tm     = 10;
unsigned long input_last_tm = 0;
unsigned long diplay_last_tm = 0;
unsigned int  lcd_backlight_cur=100;
unsigned int  prompt_time=500; // in ms for delays of instructions
//unsigned int  prompt_time=350; // for faster debugging
int  prompt_delay = 0; //to help with joystick reads and delays for inputs - this value is set during joystick read and executed later in the loop
int prompt_val;
unsigned int  video_sample_ms=100; //
unsigned int video_segments=150; //arbitrary
int reviewprog = 1;
//variables for display of remaining time
int timeh; 
int timem;
int time_s;

unsigned long start_delay_tm = 0;  //ms timestamp to help with delay comparison
unsigned int goto_shot=0;

int sequence_repeat_type=1; //1 Defaults - Run Once, 0 Continuous Loop,  -1 Continuous Forward
int sequence_repeat_count=0; //counter to hold variable for how many time we have repeated



//remote and interface variables

float joy_x_axis; int joy_x_axis_Offset; int joy_x_axis_Bucket; int joy_x_axis_Threshold; int joy_x_axis_map; int speedx;
float joy_y_axis; int joy_y_axis_Offset; int joy_y_axis_Bucket; int joy_y_axis_Threshold; int joy_y_axis_map; int speedy;
float accel_x_axis; int accel_x_axis_Offset; int accel_x_axis_Bucket; int accel_x_axis_Threshold;

int PanStepCount;
int TiltStepCount;

int z_button = 0;
int c_button = 0;
int prev_joy_x_reading=0;
int prev_joy_y_reading=0;
unsigned int joy_y_lock_count=0;
unsigned int joy_x_lock_count=0;
int prev_accel_x_reading=0;
int CZ_Button_Read_Count=0;
boolean CZ_Released=true;
int C_Button_Read_Count=0;
boolean C_Released=true;
int Z_Button_Read_Count=0;
boolean Z_Released=true;
int NCReadStatus=0; //control variable for NC error handling
unsigned int NCReadMillis=42; //frequency at which we read the nunchuck for moves  1000/24 = 42  1000/30 = 33
long NClastread=1000; //control variable for NC reads cycles




//Stepper Setup
unsigned long  feedrate_micros = 0;

struct FloatPoint {
	float x;
	float y;
 	float z;
};
FloatPoint fp;

FloatPoint current_steps;
FloatPoint target_steps;
FloatPoint delta_steps;

//our direction vars
byte x_direction = 1;
byte y_direction = 1;
byte z_direction = 1;

//End setup of Steppers

//Start of DF Vars
#define DFMOCO_VERSION 1
#define DFMOCO_VERSION_STRING "1.2.6"


// supported boards
#define ARDUINO      1
#define ARDUINOMEGA  2

//eMotimo TB3 - Set this PINOUT_VERSION 3 for TB3 Orange (Uno)
//eMotimo TB3 - Set this PINOUT_VERSION 4 for TB3 Black (MEGA)
#define PINOUT_VERSION 4

/*
  This is PINOUT_VERSION 1
  
  channel 5
        PIN  22   step
        PIN  23   direction
  channel 6
        PIN  24   step
        PIN  25   direction
  channel 7
        PIN  26   step
        PIN  27   direction
  channel 8
        PIN  28   step
        PIN  29   direction
*/

// detect board type
#define BOARD ARDUINOMEGA

#define SERIAL_DEVICE Serial
  
#define PIN_ON(port, pin)  { port |= pin; }
#define PIN_OFF(port, pin) { port &= ~pin; }

#define MOTOR_COUNT 4

#define TIME_CHUNK 50
#define SEND_POSITION_COUNT 20000

// update velocities 20 x second
#define VELOCITY_UPDATE_RATE (50000 / TIME_CHUNK)
#define VELOCITY_INC(maxrate) (max(1.0f, maxrate / 70.0f))


  //Start TB3 Black Port Mapping

  #define MOTOR0_STEP_PORT PORTE
  #define MOTOR0_STEP_PIN  B00001000 //Pin 5 PE3
  
  #define MOTOR1_STEP_PORT PORTH
  #define MOTOR1_STEP_PIN  B00001000//Pin  6 PH3
  
  #define MOTOR2_STEP_PORT PORTH
  #define MOTOR2_STEP_PIN  B00010000 //Pin 7 PH4

  #define MOTOR3_STEP_PORT PORTC //  Map this to pin 30 PC7 on the Mega board for debug
  #define MOTOR3_STEP_PIN  B10000000 //
  //End TB3 Black Port Mapping


/**
 * Serial output specialization
 */
#if defined(UBRRH)
#define TX_UCSRA UCSRA
#define TX_UDRE  UDRE
#define TX_UDR   UDR
#else
#define TX_UCSRA UCSR0A
#define TX_UDRE  UDRE0
#define TX_UDR   UDR0
#endif
 
char txBuf[32];
char *txBufPtr;

#define TX_MSG_BUF_SIZE 16

#define MSG_STATE_START 0
#define MSG_STATE_CMD   1
#define MSG_STATE_DATA  2
#define MSG_STATE_ERR   3

#define MSG_STATE_DONE  100

/*
 * Command codes from user
 */
#define USER_CMD_ARGS 40

#define CMD_NONE       0
#define CMD_HI         10
#define CMD_MS         30
#define CMD_NP         31
#define CMD_MM         40 // move motor
#define CMD_PR         41 // pulse rate
#define CMD_SM         42 // stop motor
#define CMD_MP         43 // motor position
#define CMD_ZM         44 // zero motor
#define CMD_SA         50 // stop all (hard)
#define CMD_BF         60 // blur frame
#define CMD_GO         61 // go!

#define CMD_JM         70 // jog motor
#define CMD_IM         71 // inch motor

#define MSG_HI 01
#define MSG_MM 02
#define MSG_MP 03
#define MSG_MS 04
#define MSG_PR 05
#define MSG_SM 06
#define MSG_SA 07
#define MSG_BF 10
#define MSG_GO 11
#define MSG_JM 12
#define MSG_IM 13


struct UserCmd
{
  byte command;
  byte argCount;
  int32_t args[USER_CMD_ARGS];
} ;

/*
 * Message state machine variables.
 */
byte lastUserData;
int  msgState;
int  msgNumberSign;
UserCmd userCmd;


struct txMsg
{
  byte msg;
  byte motor;
};

struct TxMsgBuffer
{
  txMsg buffer[TX_MSG_BUF_SIZE];
  byte head;
  byte tail;
};

TxMsgBuffer txMsgBuffer;


/*
 Motor data.
 */

uint16_t           motorAccumulator0;
uint16_t           motorAccumulator1;
uint16_t           motorAccumulator2;
uint16_t           motorAccumulator3;

uint16_t*          motorAccumulator[MOTOR_COUNT] =
{
  &motorAccumulator0, &motorAccumulator1, &motorAccumulator2, &motorAccumulator3, 

};

uint16_t           motorMoveSteps0;
uint16_t           motorMoveSteps1;
uint16_t           motorMoveSteps2;
uint16_t           motorMoveSteps3;

uint16_t*          motorMoveSteps[MOTOR_COUNT] =
{
  &motorMoveSteps0, &motorMoveSteps1, &motorMoveSteps2, &motorMoveSteps3,
};


uint16_t           motorMoveSpeed0;
uint16_t           motorMoveSpeed1;
uint16_t           motorMoveSpeed2;
uint16_t           motorMoveSpeed3;

uint16_t         * motorMoveSpeed[MOTOR_COUNT] =
{
  &motorMoveSpeed0, &motorMoveSpeed1, &motorMoveSpeed2, &motorMoveSpeed3,

};

volatile boolean nextMoveLoaded;


unsigned int   velocityUpdateCounter;
byte           sendPositionCounter;
boolean        hardStopRequested;

byte sendPosition = 0;
byte motorMoving = 0;
byte toggleStep = 0;


#define P2P_MOVE_COUNT 7

struct Motor
{
  byte   stepPin;
  byte   dirPin;

  // pre-computed move
  float   moveTime[P2P_MOVE_COUNT];
  int32_t movePosition[P2P_MOVE_COUNT];
  float   moveVelocity[P2P_MOVE_COUNT];
  float   moveAcceleration[P2P_MOVE_COUNT];

  float   gomoMoveTime[P2P_MOVE_COUNT];
  int32_t gomoMovePosition[P2P_MOVE_COUNT];
  float   gomoMoveVelocity[P2P_MOVE_COUNT];
  float   gomoMoveAcceleration[P2P_MOVE_COUNT];

  int       currentMove;
  float     currentMoveTime;
  
  volatile  boolean   dir;

  int32_t   position;
  int32_t   destination;
  
  float     maxVelocity;     //Orig - delete later
  float     maxAcceleration; //Orig - delete later
  
  float     moveMaxVelocity;     //Pass this into calculator for synchronized moves
  float     moveMaxAcceleration; //Pass this into calculator for synchronized moves
  
  float     jogMaxVelocity; //replaced the original maxVelocity
  float     jogMaxAcceleration; //replaced the original maxAcceleration
 
  uint16_t  nextMotorMoveSteps;
  float     nextMotorMoveSpeed;
  

};

boolean maxVelLimit=false;

boolean goMoReady;
int     goMoDelayTime;

Motor motors[MOTOR_COUNT];

//End of DFVars


/* 
 =========================================
 Setup functions
 =========================================
*/



void setup() {
 
  // setup motor pins
 pinMode(MOTOR0_STEP, OUTPUT);
 pinMode(MOTOR0_DIR, OUTPUT);
 pinMode(MOTOR1_STEP, OUTPUT);
 pinMode(MOTOR1_DIR, OUTPUT);
 pinMode(MOTOR2_STEP, OUTPUT);
 pinMode(MOTOR2_DIR, OUTPUT);
 
pinMode(MS1,OUTPUT);
pinMode(MS2,OUTPUT);
pinMode(MS3,OUTPUT);
 
digitalWrite(MS1, HIGH);
digitalWrite(MS2, HIGH);
digitalWrite(MS3, HIGH);

 pinMode(MOTOR_EN, OUTPUT);
 pinMode(MOTOR_EN2, OUTPUT);
 digitalWrite(MOTOR_EN, HIGH); //LOW Enables output, High Disables
 digitalWrite(MOTOR_EN2, HIGH); //LOW Enables output, High Disables
 
// setup camera pins
 pinMode(CAMERA_PIN, OUTPUT); 
 pinMode(FOCUS_PIN, OUTPUT); 
 
digitalWrite(CAMERA_PIN, LOW);
digitalWrite(FOCUS_PIN, LOW);

//Setup of I/0 Pings Start with output of I/Oport
pinMode(IO_2, OUTPUT);
pinMode(IO_3, OUTPUT);

digitalWrite(IO_2, LOW);
digitalWrite(IO_3, LOW);

pinMode(A0, INPUT); //this is for the voltage reading

//Setup LCD
 lcd.setup();  
 delay(100);
 draw(0,1,2); // Setup Complete
 draw(1,2,1); // Version Number
 //strcpy_P(lcdbuffer1, (PGM_P)pgm_read_word(&(setup_str[0]))); // Necessary casts and dereferencing, just copy.
 //lcd.at(2,1,lcdbuffer1);
 lcd.contrast(50);
 lcd.cursorOff();
 lcd.bright(4);
 
 delay(prompt_time*2);
 lcd.empty();
 delay(100);

 draw(2,1,1); // Connect Joystick

//Setup Serial Connection

//if (DEBUG) Serial.begin(115200);
//else Serial.begin(57600);
Serial.begin(57600);
Serial.println("Opening Serial Port");

// Handle EEPROM Interaction and upgrades

//Check to see if our hardcoded build version set in progam is different than what was last put in EEPROM - detect upgrade.
if(build_version != check_version()) { //4 byte string that now holds the build version.
  if(DEBUG) Serial.println(check_version());
  if(DEBUG) Serial.println("Upgrading Memory");   
  write_defaults_to_eeprom_memory();  //these are for setting for last shot
  set_defaults_in_setup(); //this is for our setup values that should only be defaulted once.
  //review_RAM_Contents();
}
else { //load last setting into memory - no upgrade
   if(DEBUG) Serial.println("Restoring EEPROM Values");
   restore_from_eeprom_memory();
   //review_RAM_Contents();
 }
//End Setup of EEPROM

//begin  Setup for Nunchuck
Nunchuck.init(0);
delay(50);
for (int reads=1; reads<17; reads++) {
   Nunchuck.getData();
   //Nunchuck.printData();
   lcd.at(2,reads,"+");
   if (abs(Nunchuck.joyx()-127)>60||abs(Nunchuck.joyy()-127)>60 ){
     lcd.empty();
     draw(57,1,1);//lcd.at(1,1,"Center Joystick"); 
     reads=1;
   }
   delay(10);
   
}

calibrate_joystick(Nunchuck.joyx(),Nunchuck.joyy());

 //end  Setup for Nunchuk
 lcd.empty(); 
 

//Setup Motors  
init_steppers();

//init_external_triggering();
pinMode(IO_3, INPUT);
digitalWrite(IO_3, HIGH);
attachInterrupt(1, cam_change, CHANGE); 



} //end of setup

void loop() {  //Main Loop
  while(1) {  //use debugging WHEN HIT here for monitoring - {sequence_repeat_type},{progstep},{progtype},{camera_fired}
    switch (progstep) 
    {

 //start of 2 point SMS/Video routine
      case 0:   // 
        Choose_Program();
		
      break;
      
      case 1:   // Move to Start Point
        Move_to_Startpoint(); //don't jump in this loop by accident
      break;
            
      case 2:   // Move to End Point
        Move_to_Endpoint(); //don't jump in this loop by accident
      break;
      
      case 3: //  Set Camera Interval
        Set_Cam_Interval();
      break;
     
      case 4: // 
        Set_Duration();
      break;
      
      case 5: //  	    Static Time
	  
	  if (intval==VIDEO_INTVAL) {   //don't show this for video
	      if (progstep_forward_dir) progstep_forward(); //skip the menu, go forward
	      else progstep_backward();  //skip the menu, go backward
      }
      else  Set_Static_Time(); //not needed for video
	  
      break;
         
      case 6: //  
	  	
		Set_Ramp();
		
      break;
       
      case 7: //  Lead in and lead out
       
	   if (intval==VIDEO_INTVAL) {   //don't show this for video
			if (progstep_forward_dir) {
				Calculate_Shot(); //
				progstep_forward();
			} //skip the menu, go forward
	        else progstep_backward();  //skip the menu, go backward
       }
       
	   else  Set_LeadIn_LeadOut(); //  not needed for video
		
		
      break;       
        
       case 8: //  Set Shot Type
       	   if (intval!=VIDEO_INTVAL) {   //skip for non video
	       	   if (progstep_forward_dir) {
					progstep_forward();  //skip the menu, go forward
	       	   } 
	       	   else progstep_backward();  //skip the menu, go backward
       	   }
       	   
       	   else Set_Shot_Repeat(); 
       break;
  
      case 9: //  review and confirm
        Review_Confirm(); //also has the delay start options here
      break;
      
//end of the two point move
      
 //start of the three point move      
       case 100:
        Choose_Program();
      break;
      
      case 101:   // Move Point 0
          Move_to_Point_X(0);
      break;
            
      case 102:   // Move Point 1
          Move_to_Point_X(1);
      break;      
      
      case 103:   // Move Point 2
          Move_to_Point_X(2);
      break; 
      
      case 104: //  Set Camera Interval
        Set_Cam_Interval();
      break;
     
      case 105: // 
        Set_Duration();
      break;
      
      case 106: //  
        Set_Static_Time();
      break;
         
      case 107: //  
        Set_Ramp();
      break;
       
      case 108: //  
        Set_LeadIn_LeadOut();
      break;       
        
      case 109: //  review and confirm
        Review_Confirm();
      break;
 //end of the three point move     
 
 //start of pano Mode
     
          //  define field of view
       //We want to know how wide and tall our field of view is in steps so we can get our overlap right.  Anytime you zoom or change lenses, this need to be redefined
       //This should be a 10 seconds process to define by specifying corners
       //Step 1 - Put a point in the upper right corner - set zeros, pan up and right to hit same point with lower left corner of viewfinder
       //Display values  - write to ram - use these values 
      
      case 200:  //
        Choose_Program();      
      break;
	  
	  case 201:  //
	    Move_to_Point_X(0); //move to sharp point 
	  break;
     
      case 202:  //
         Set_angle_of_view();
      break;
            
      case 203:   //
        Define_Overlap_Percentage();
      break;      
      
      case 204:   // 
        Move_to_Point_X(0);
      break; 
      
      case 205: //  
        Move_to_Point_X(1);
      break;
     
      case 206: // 
          Set_Static_Time();   
      break;
      
      case 207: //  
        Pano_Review_Confirm();  
      break;
 //end of Pano Mode
    
    
    
 //start of Portrait Pano Method
     
       //  define field of view
       //We want to know how wide and tall our field of view is in steps so we can get our overlap right.  Anytime you zoom or change lenses, this need to be redefined
       //This should be a 10 seconds process to define by specifying corners
       //Step 1 - Put a point in the upper right corner - set zeros, pan up and right to hit same point with lower left corner of viewfinder
       //Display values  - write to ram - use these values 
      
      case 210:  //
        Choose_Program();      
      break;
      
      case 211:  //
        Move_to_Point_X(0); //move to sharp point      
      break;
     
      case 212:  //
         Set_angle_of_view();
      break;
            
      case 213:   //
        Define_Overlap_Percentage();
      break;      
      
      case 214:   // 
        Move_to_Point_X(0);  //set subject point
      break; 
      
      case 215: //  
        Set_PanoArrayType();   //this sets variable that define how we move camera - load the appropriate array.
      break;
     
      case 216: // 
          Set_Static_Time();   
      break;
      
      case 217: //  
        Pano_Review_Confirm();  
      break;
 //end of Pano Mode
    
 
 
 
 //start of entered distance on aux mode
      case 300:   // 
        Choose_Program();
      break;
      
      case 301:   // Move to Start Point
        Move_to_Startpoint();
      break;
            
      case 302:   // Move to End Point
        Enter_Aux_Endpoint();
      break;
      
      case 303: //  Set Camera Interval
        Set_Cam_Interval();
      break;
     
      case 304: // 
        Set_Duration();
      break;
      
      case 305: //  
        Set_Static_Time();
      break;
         
      case 306: //  
        Set_Ramp();
      break;
       
      case 307: //  
        Set_LeadIn_LeadOut();
      break;       
        
      case 308: //  review and confirm
        Review_Confirm();
      break;
      
//end entered distance mode
      
 //start of setup      
 
      case 901:   // AUX_ON
        Setup_AUX_ON();
      break;
            
      case 902:   // PAUSE_ENABLED
        Setup_PAUSE_ENABLED();
      break;      
      
      case 903:   // POWERSAVE_PT
        Setup_POWERSAVE_PT();
      break; 
      
      case 904: //  POWERSAVE_AUX
        Setup_POWERSAVE_AUX();
      break;
      
      case 905: //  LCD Bright
        Setup_LCD_BRIGHTNESS_DURING_RUN();
      break;
      
      case 906: //  Aux Motor Max Speed
        Setup_Max_AUX_Motor_Speed();
      break;
      
      case 907: //  LCD Bright
        Setup_AUX_Motor_DIR();
      break;
      
     
      case 908: //  Exit
        delay(100);
      break;
     
    
//end of setup       

 //start of in program menu options      
 
      case 1001:   // AUX_ON
        InProg_Select_Option();
      break;
            
     
     
    
//end of in program menu  

        
      
case 50:  // loop for SMS
    
    // //Step 1 if internal interval.Kick off the shot sequence. This happens once per camera shot.   
      if( (intval>3) && (Program_Engaged) && !(Shot_Sequence_Engaged) && ((millis() - interval_tm) > interval) ) { 
        interval_tm_last=interval_tm; //just used for shot timing comparison
        interval_tm=millis(); //start the clock on our shot sequence
        
        if (DEBUG) {Serial.print("trueinterval: ");Serial.print(interval_tm-interval_tm_last);Serial.print(";");}
        Interrupt_Fire_Engaged=false; //clear this flag to avoid rentering this routine
        Shot_Sequence_Engaged=true;//
        Prefire_Engaged=true;//
        IO_Engaged=true;//
        digitalWrite(FOCUS_PIN, HIGH); //for longer shot interval, wake up the camera
 
        if (POWERSAVE_PT<4)   enable_PT();  //don't power on for shot for high power saving
        if (AUX_ON && POWERSAVE_AUX<4)   enable_AUX();  //don't power on for shot for high power saving

      }
      
      //Step 1 if external triggering. This happens once per camera shot.
      if( (Program_Engaged) && !(Shot_Sequence_Engaged) && (intval==EXTTRIG_INTVAL) && Interrupt_Fire_Engaged ) { 
        interval_tm_last=interval_tm; //just used for shot timing comparison
        
        interval_tm=millis(); //start the clock on our shot sequence
        if (DEBUG) {Serial.print("trueinterval: ");Serial.print(interval_tm-interval_tm_last);Serial.print(";");}
        Interrupt_Fire_Engaged=false; //clear this flag to avoid rentering this routine

        Shot_Sequence_Engaged=true;//
        Prefire_Engaged=true;//
        IO_Engaged=true;//
        digitalWrite(FOCUS_PIN, HIGH); //for longer shot interval, wake up the camera
        
        if (POWERSAVE_PT<4)   enable_PT();  //don't power on for shot for high power saving
        if (AUX_ON && POWERSAVE_AUX<4)   enable_AUX();  //don't power on for shot for high power saving
      }
         
             
      //End our prefire - check that we are in program active,shot cycle engaged, and prefire engaged and check against our prefire time
      //If so set prefire flag off, static flag on, fire camera for static time value, update the display 		

      if ((Shot_Sequence_Engaged) && (Prefire_Engaged)  && ((millis()-interval_tm) > prefire_time*100)) { 
 
        Prefire_Engaged=false;
        if (DEBUG) {Serial.print("PreDoneAt ");Serial.print(millis()-interval_tm);Serial.print(";");}
        
        Static_Time_Engaged=true;
       //Fire Camera
          if (intval!=3) fire_camera((long)static_tm*100); //start shutter sequence
          camera_fired++;
      }

      //End out static time - check that we are in an program active and static time,  Shutter not engaged, check shot cycle time agains prefire+statictime
      //If so remove flags from Static Time Engaged and IO engaged, Turn off I/O port, set flags for motors moving, move motors
      //move motors - figure out delays.   Long delays mean really slow - choose the minimum of the calculated or a good feedrate that is slow
	     
      //if (Program_Engaged && Shot_Sequence_Engaged && Static_Time_Engaged && !Shutter_Signal_Engaged && ((millis() - interval_tm) > (prefire_time*100+static_tm*100)) ) {
      if (Shot_Sequence_Engaged && Static_Time_Engaged && !Shutter_Signal_Engaged && ((millis() - interval_tm) > (prefire_time*100+static_tm*100)) ) 
      { //removed requirement for Program Engaged for external interrupt
   
       
        Static_Time_Engaged=false; //Static Time Engaged is OFF
        IO_Engaged=false; //IO Engaged is off
          //digitalWrite(IO_2, LOW); //Use this as the iterrupt
          //digitalWrite(IO_3, LOW);  //Turn off Pin 3
          //Serial.print("IO3_off"); //Serial.println(millis()-interval_tm);
        
       
        //Move the motors - each motor move is calculated by where we are in the sequence - we still call this for lead in and lead out - motors just don't move
 
          Move_Engaged=true; //move motors  
          if (DEBUG_MOTOR) {Serial.print("MoveStart "); Serial.print(millis()-interval_tm);Serial.print(";");}
          move_motors();
          if (DEBUG_MOTOR) {Serial.print("Moveend "); Serial.print(millis()-interval_tm);Serial.print(";");}
          
        //Turn off the motors if we have selected powersave 3 and 4 are the only ones we want here
          if (POWERSAVE_PT>2)   disable_PT(); 
          if (POWERSAVE_AUX>2)   disable_AUX();  //
   
          
        //Update display
          if (intval!=3) display_status();  //update after shot complete to avoid issues with pausing
    

       Shot_Sequence_Engaged=false;  //Shot sequence engaged flag is is off - we are ready for our next 
       Interrupt_Fire_Engaged=false;
       //CZ_Button_Read_Count=0;
       //InterruptAction_Reset(); //enable the external interrupts to start a new shot
       if (DEBUG) {Serial.println("EOL");} 
      }
      
      if ( camera_moving_shots > 0  && camera_fired >= camera_total_shots) {  //end of program
        lcd.empty();
        draw(58,1,1);//lcd.at(1,1,"Program Complete"); 
        Program_Engaged=false;
        if (POWERSAVE_PT>1)   disable_PT();  //  low, standard, high, we power down at the end of program
        if (POWERSAVE_AUX>1)  disable_AUX();  // low, standard, high, we power down at the end of program
        delay(prompt_time*2);
        progstep=90;
        first_time=1;
      }
      
  //This portion always runs in empty space of loop.      
      
    NunChuckQuerywithEC();
    NunChuckjoybuttons();
    Check_Prog(); //look for button presses
    //if (CZ_Button_Read_Count>10 && intval==EXTTRIG_INTVAL ) Interrupt_Fire_Engaged=true; // manual trigger
    //if (PAUSE_ENABLED && CZ_Button_Read_Count>10 && intval>3 && !Shot_Sequence_Engaged ) Pause_Prog(); //pause an SMS program
    if (PAUSE_ENABLED && CZ_Button_Read_Count>25 && intval>3 && !Shot_Sequence_Engaged && CZ_Released ) SMS_In_Shoot_Paused_Menu(); //jump into shooting menu
    

break; //break 50      
      
 
 
 
case 51:  

//main video loop interrupt based.  This runs for 2 point moves only.
   
if (progtype==REG2POINTMOVE || progtype==REV2POINTMOVE) {
   synched3AxisMove_timed(motor_steps_pt[2][0],motor_steps_pt[2][1],motor_steps_pt[2][2], float(overaldur), float(rampval/100.0));
   if (maxVelLimit){ //indicates the move is limited to enforce velocity limit on motors)
     lcd.at(2,1,"Speed Limit");
   }
    //Start us moving 
  // interval_tm_last=interval_tm;
   interval_tm=millis();  
    
    startISR1 ();
      do 
      {
        if (!nextMoveLoaded)
        {
          updateMotorVelocities();
        }
      } while (motorMoving);

    stopISR1 ();

    Serial.print("Video Runtime"); Serial.println(millis()-interval_tm);  

    
    
    

      if (!motorMoving&&(sequence_repeat_type==0)) { //new end condition for RUN CONTINOUS
			boolean break_continuous=false;
			lcd.empty(); 
			draw(58,1,1);//lcd.at(1,1,"Program Complete"); 
			Program_Engaged=false;
			for (int i=0; i<30; i++){
			    NunChuckQuerywithEC();
			    NunChuckjoybuttons();
			    Check_Prog(); //look for button presses
			    if (PAUSE_ENABLED && CZ_Button_Read_Count>25 ) {
					break_continuous=true;
					lcd.empty();				
					lcd.at(1,1,"Stopping Run");
					lcd.at(2,1,"Release Buttons");
					do {
					NunChuckQuerywithEC();
					NunChuckjoybuttons();	
										
					} while (c_button || z_button);
					progstep=9;
					}
				
			}
			
			//add section to delay here if the delay is set.
			while (start_delay_tm>millis()/1000L) {
				//enter delay routine
				calc_time_remain_start_delay ();
				if ((millis()-diplay_last_tm) > 1000) display_time(2,1);
				NunChuckQuerywithEC();
				NunChuckjoybuttons();
				Check_Prog(); //look for long button press
				//if (CZ_Button_Read_Count>20 && !Program_Engaged) {
				//	start_delay_tm=((millis()/1000L)+5); //start right away by lowering this to 5 seconds.
				//	CZ_Button_Read_Count=0; //reset this to zero to start
				//}

			}
			
			//end start delay
			
			
			if(!break_continuous) Auto_Repeat_Video(); //only run this if there isn't a break command
			first_time=1;
      }
	  else if (!motorMoving&&(sequence_repeat_type==1)) { //new end condition for RUN ONCE
		        lcd.empty();
		        draw(58,1,1);//lcd.at(1,1,"Program Complete");
		        Program_Engaged=false;
		        if (POWERSAVE_PT>1)   disable_PT();  //  low, standard, high, we power down at the end of program
		        if (POWERSAVE_AUX>1)  disable_AUX();  // low, standard, high, we power down at the end of program
		        progstep=90;
		        first_time=1;
		        delay(100);
		        //NunChuckQuerywithEC();
	  }
	  
	  
      
} // end interrupt routine driven for 2 points

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

  //Start video loop for 3 Point moves - this loop does not use the new motor move profile as it needs to calculate each and every segment
if (progtype==REG3POINTMOVE || progtype==REV3POINTMOVE) {  //this is regular 3 point move program that can be modified later
      if (DEBUG) {
            interval_tm_last=interval_tm;
            interval_tm=millis(); 
          }
      //Start us moving  
      
      if (DEBUG) {Serial.print("trueinterval ");Serial.print(interval_tm-interval_tm_last);Serial.print(";");}
       
      if (DEBUG_MOTOR) {Serial.print("MoveStart "); Serial.print(millis());Serial.print(";");}
      
      camera_fired ++; //still need this for framing
      move_motors();
      
      if (DEBUG_MOTOR) {Serial.print("Moveend "); Serial.println(millis());}
          

      if ( camera_total_shots > 0  && camera_fired >= camera_total_shots) { 
        lcd.empty();
        //draw(58,1,1);//lcd.at(1,1,"Program Complete"); 
        Program_Engaged=false;
        if (POWERSAVE_PT>1)   disable_PT();  //  low, standard, high, we power down at the end of program
        if (POWERSAVE_AUX>1)  disable_AUX();  // low, standard, high, we power down at the end of program
        delay(prompt_time*2);
        progstep=90;  
        first_time=1;
        //delay(100);
        //NunChuckQuerywithEC();
      }

} // End video loop for 3 Point moves


break; //break 51 - VIDEO



case 52:  // loop for external interrupt - external triggering
    
    //New interrupt Flag Checks
      
      if (changehappened)
      {
          changehappened=false;
          if(!state) //start the clock as the cam shutter witch closed and sense pin, was brought low
          {
            ext_shutter_open=true;
            shuttertimer_open=micros(); 
            if(DEBUG) Serial.print("shuttertimer_a=");Serial.print(shuttertimer_open);
            
          }
          else if (state) //shutter closed - sense pin goes back high - stop the clock and report
          {
              ext_shutter_open=false;  
              shuttertimer_close=micros(); //turn on the led / shutter
               ext_shutter_count++;
             if(DEBUG) Serial.print(" ext_shutter_count=");Serial.print(ext_shutter_count);
             if(DEBUG) Serial.print(" shuttertimer_b=");Serial.print(shuttertimer_close);Serial.print("diff=");Serial.println(shuttertimer_close-shuttertimer_open);
          }
          
      }
      //end interrupt check and flagging
     
             
      //  Start of states for external shooting loop	

      if( (Program_Engaged) && !(Shot_Sequence_Engaged) && !(Shutter_Signal_Engaged) && (ext_shutter_open) ) { //start a shot sequence flag
      
          Shot_Sequence_Engaged=true; //
      
      }  
        
        
      if( (Program_Engaged) && (Shot_Sequence_Engaged) && !(Shutter_Signal_Engaged) && (ext_shutter_open) ) { //fire the camera can happen more than once in a shot sequence with HDR
         
          if (DEBUG) {Serial.print("Startshot_at:");Serial.print(millis());Serial.println(";");}
      
       //Fire Camera
          //don't fire the camera with the timer, just turn on our focus and shutter pins - we will turn them off when we sense the shot is done.
          digitalWrite(FOCUS_PIN, HIGH);
          digitalWrite(CAMERA_PIN, HIGH);
          Shutter_Signal_Engaged=true;
          //camera_fired++;
      }

   	     
       if (Shot_Sequence_Engaged && (Shutter_Signal_Engaged) && !(ext_shutter_open) ) { //shutter just closed, stop the camera port and move
       
          digitalWrite(FOCUS_PIN, LOW);
          digitalWrite(CAMERA_PIN, LOW);
          Shutter_Signal_Engaged=false;
       
        
            if (ext_shutter_count >=ext_hdr_shots) { //this is future functionality  - leave at 1 for now
            
                    camera_fired++;
                    ext_shutter_count=0;  
            //Move the motors - each motor move is calculated by where we are in the sequence - we still call this for lead in and lead out - motors just don't move
           
                    Move_Engaged=true; //move motors  
                    if (DEBUG_MOTOR) {Serial.print("MoveStart "); Serial.print(millis()-interval_tm);Serial.print(";");}
                    move_motors();
                    if (DEBUG_MOTOR) {Serial.print("Moveend "); Serial.print(millis()-interval_tm);Serial.print(";");}
                    
            //Turn off the motors if we have selected powersave 3 and 4 are the only ones we want here
              if (POWERSAVE_PT>2)   disable_PT(); 
              if (POWERSAVE_AUX>2)   disable_AUX();  //  
             
                  
                  //Update display
                    display_status();  //update after shot complete to avoid issues with pausing
           
                   Shot_Sequence_Engaged=false;  //Shot sequence engaged flag is is off - we are ready for our next 
                   CZ_Button_Read_Count=0;
                   //InterruptAction_Reset(); //enable the external interrupts to start a new shot
                   if (DEBUG) {Serial.println("EOL");}
            }
             
      }
      
      if ( camera_moving_shots > 0  && camera_fired >= camera_total_shots) {  //end of program
        lcd.empty();
        draw(58,1,1);//lcd.at(1,1,"Program Complete"); 
        Program_Engaged=false;
        if (POWERSAVE_PT>1)   disable_PT();  //  low, standard, high, we power down at the end of program
        if (POWERSAVE_AUX>1)  disable_AUX();  // low, standard, high, we power down at the end of program
        delay(prompt_time*2);
        progstep=90;
        first_time=1;
      }
    NunChuckQuerywithEC();
    NunChuckjoybuttons();
    Check_Prog(); //look for button presses
    if (CZ_Button_Read_Count>10 && intval==EXTTRIG_INTVAL ) Interrupt_Fire_Engaged=true; // manual trigger
    //if (PAUSE_ENABLED && CZ_Button_Read_Count>20 && intval>3 && !Shot_Sequence_Engaged ) Pause_Prog(); //pause an SMS program

break; //break 52 - end external triggering loop



case 90: // end of program - offer repeat and reverse options - check the nuncuck
          if (first_time==1){
            lcd.empty();
            lcd.at(1,4,"Repeat - C");
            lcd.at(2,4,"Reverse - Z");
            NunChuckQuerywithEC();
            first_time=0;
            delay(100);
          }
		  
	  //This portion always runs in empty space of loop.
  
	  NunChuckQuerywithEC();
	  NunChuckjoybuttons();
	  Check_Prog(); //look for button presses
 	 //add error handling here to prevent accidental starts
	  //if (CZ_Button_Read_Count>25  && CZ_Released ) button_actions_end_of_program();  //Repeat or Reverses
	  button_actions_end_of_program();
	  //delay(1); //don't just hammer on this - query at regular interval

break;  // break 90

case 250:  // loop for Pano
    
    //Kick off the shot sequence!!!  This happens once per camera shot.   
      if( (intval>2) && (Program_Engaged) && !(Shot_Sequence_Engaged) && ((millis() - interval_tm) > interval) ) { 
        interval_tm_last=interval_tm; //just used for shot timing comparison
        
        interval_tm=millis(); //start the clock on our shot sequence
        if (DEBUG) {Serial.print("trueinterval: ");Serial.print(interval_tm-interval_tm_last);Serial.print(";");}
        Interrupt_Fire_Engaged=false; //clear this flag to avoid re-entering this routine

        Shot_Sequence_Engaged=true;//
        Prefire_Engaged=true;//
        IO_Engaged=true;//
        digitalWrite(FOCUS_PIN, HIGH); //for longer shot interval, wake up the camera
     
        //if (POWERSAVE_PT<4)   enable_PT();  //don't power on for shot for high power saving
        //if (AUX_ON && POWERSAVE_AUX<4)   enable_AUX();  //don't power on for shot for high power saving
        enable_PT();

      }
      
  
             
      //End our prefire - check that we are in program active,shot cycle engaged, and prefire engaged and check against our prefire time
      //If so set prefire flag off, static flag on, fire camera for static time value, update the display 		

      if ((Shot_Sequence_Engaged) && (Prefire_Engaged)  && ((millis()-interval_tm) > prefire_time*100)) { 
 
        Prefire_Engaged=false;
        if (DEBUG) {Serial.print("PreDoneAt ");Serial.print(millis()-interval_tm);Serial.print(";");}
        
        Static_Time_Engaged=true;
       //Fire Camera
          fire_camera((long)static_tm*100); //start shutter sequence
          camera_fired++;
      }

      //End out static time - check that we are in an program active and static time,  Shutter not engaged, check shot cycle time against prefire+statictime
      //If so remove flags from Static Time Engaged and IO engaged, Turn off I/O port, set flags for motors moving, move motors
      //move motors - figure out delays.   Long delays mean really slow - choose the minimum of the calculated or a good feedrate that is slow
	     
      //if (Program_Engaged && Shot_Sequence_Engaged && Static_Time_Engaged && !Shutter_Signal_Engaged && ((millis() - interval_tm) > (prefire_time*100+static_tm*100)) ) {
      if (Shot_Sequence_Engaged && Static_Time_Engaged && !Shutter_Signal_Engaged && ((millis() - interval_tm) > (prefire_time*100+static_tm*100)) ) { //removed requirement for Program Engaged for external interrupt
   
       
        Static_Time_Engaged=false; //Static Time Engaged is OFF
        IO_Engaged=false; //IO Engaged is off
          //digitalWrite(IO_2, LOW); //Use this as the iterrupt
          //digitalWrite(IO_3, LOW);  //Turn off Pin 3
          //Serial.print("IO3_off"); //Serial.println(millis()-interval_tm);
        
       
        //Move the motors - each motor move is calculated by where we are in the sequence - we still call this for lead in and lead out - motors just don't move
 
          Move_Engaged=true; //move motors  
          if (DEBUG_MOTOR) {Serial.print("MoveStart "); Serial.print(millis()-interval_tm);Serial.print(";");}
          if (DEBUG_PANO) Serial.print("progtype "); Serial.println(progtype);
          if (progtype==PANOGIGA)//regular pano
            {       
              if (P2PType==0)
              {
               move_motors_pano_basic();
              }
              else if (P2PType==1)
              {
                move_motors_pano_accel();
              }
            }
            
           else if (progtype==PORTRAITPANO) //PORTRAITPANO method array load
            {       
                if (DEBUG_PANO) Serial.print("entered PORTRAITPANO loop");   
                move_motors_accel_array();
                delay (PanoPostMoveDelay);
            }
            
            
            
            
            
          //
          if (DEBUG_MOTOR) {Serial.print("Moveend "); Serial.print(millis()-interval_tm);Serial.print(";");}
          
        //Turn off the motors if we have selected powersave 3 and 4 are the only ones we want here
          //if (POWERSAVE_PT>2)   disable_PT(); 
          //if (POWERSAVE_AUX>2)   disable_AUX();  //
   
          //
          
          
          if (P2PType==0)
            {
                       Serial.println("finished basic move");
                       if (intval!=3) display_status();  //update after shot complete to avoid issues with pausing
                       Move_Engaged=false;
                       Shot_Sequence_Engaged=false;  //Shot sequence engaged flag is is off - we are ready for our next 
                       Interrupt_Fire_Engaged=false;
                       CZ_Button_Read_Count=0;
                       //InterruptAction_Reset(); //enable the external interrupts to start a new shot
                       if (DEBUG) {
                         Serial.println("EOL");
                       }
            }

      } //end test 

      //just have this repeat like we are in loop
          if (P2PType==1) //acceleration profiles
            {
              
              if (!nextMoveLoaded)  
                  {
                      updateMotorVelocities();  //finished up the interrupt routine 
                      //Print_Motor_Params(2);
                  }
              
               //test for completed move
               if (Shot_Sequence_Engaged && Move_Engaged && motorMoving==0)  //motors completed the move
                  { 
                       Serial.println("finished accel move");
                       if (intval!=3) display_status();  //update after shot complete to avoid issues with pausing
                       Move_Engaged=false;
                       Shot_Sequence_Engaged=false;  //Shot sequence engaged flag is is off - we are ready for our next 
                       Interrupt_Fire_Engaged=false;
                       CZ_Button_Read_Count=0;
                       //InterruptAction_Reset(); //enable the external interrupts to start a new shot
                       if (DEBUG) {
                         Serial.println("EOL");
                         }
                   
                   } 
            }
      
    
      
      if ( camera_moving_shots > 0  && camera_fired >= camera_total_shots) {  //end of program
        lcd.empty();
        draw(58,1,1);//lcd.at(1,1,"Program Complete"); 
        Program_Engaged=false;
        if (POWERSAVE_PT>1)   disable_PT();  //  low, standard, high, we power down at the end of program
        if (POWERSAVE_AUX>1)  disable_AUX();  // low, standard, high, we power down at the end of program
        delay(2000);
        progstep=290;
        first_time=1;
      }
    //updateMotorVelocities();  //uncomment this for DF Loop
    NunChuckQuerywithEC();
    NunChuckjoybuttons();
    //Check_Prog(); //look for button presses
    // if (CZ_Button_Read_Count>10 && intval==EXTTRIG_INTVAL ) Interrupt_Fire_Engaged=true; // manual trigger
    // if (PAUSE_ENABLED && CZ_Button_Read_Count>20 && intval>3 && !Shot_Sequence_Engaged ) Pause_Prog(); //pause an SMS program

    break; //break 250


case 290: //  finished up pano
          if (first_time==1){
            lcd.empty();
            stopISR1();  
            draw(58,1,1);//lcd.at(1,1,"Program Complete");
            draw(59,2,1);//lcd.at(2,1," Repeat Press C");
            NunChuckQuerywithEC();
            first_time=0;
            delay(100);
          }
          NunChuckQuerywithEC();
          NunChuckjoybuttons();
          button_actions290();  //read buttons, look for c button press to start run
break;  // break 90
   

    } //switch
  } // while
} //loop


Hi,
PLEASE try one of the EXAMPLE codes in the IDE for the library.

PLEASE FORGET about your code for now and run code that JUST uses the display.

You need to find the problem, and using your code with all the extra stuff in it is not the way to get to the problem.

Just grabbing a code and expecting it to work with little or no experience is courting problems.

Can I suggest you Google for "Arduino Tutorial" and follow one of those and get used to doing smaller things before attempting a block of unkown and complex code?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

I have been watching tutorials and am trying to learn. I do not expect to be able to grab a code and expect it to work without problems which is why I am asking for help. I had absolutely no Idea where to even start.
Thanks for the input.

Hi,
Okay so you haven't realised that the code you posted on post #17 has no reference to the hd44780 code.

So I suggest you just get the display code working, using Example codes.
Google;

how to use the hd44780 library

There are numerous examples and tutorials.

Tom.. :smiley: :+1: :coffee: :australia: