Ok, so after 5 days, I'm just going to beg...

Thank you in advance for reading this. As I am nearly at my wits end trying to make this work.

----> Basic Scenario:
Need to Interface Arduino with a device, that has 4 positions and OFF. Then cycles back to Position # 1.
So 5 button clicks Cycle the device… A Long Press Saves the ON position in case power is lost.

----> What I have Accomplished:
Power Arduino from the Device we wish to interface with - Done
Take the Devices own button, and Wire it up to the Arduino with a Pulldown Resistor - Done
Create a Homemade optocoupler using a photo-resistor and an LED + shrink Tubing - Done
Test the coupler to see if it manipulates the device, it does! 50ms blink, changes our position up +1

----> Complete Scenario
Now that I have an Interface with the original button that I can control from my Nano, I need to make it “Behave” in the following manner…

AutoButtonPress = Button Automatically records a press every 24 hours, and blinks the LED for 50ms
ManualSinglePress = After a short Pause, Blinks once for 50ms
ManualDoublePress = Resets the counter to 24 Hours
ManualLongPress = After a short Pause, LED lights for 5 Seconds to SAVE home position on the original device.
OutputToSerial = Show all actions on serial console for troubleshooting purposes
OutputCounterToDisplay = Output the 24 hour countdown to a display of some kind. To see when it is reset. As well as Status.

----> What I cannot Figure out

  1. I am having a hard time understanding the Structure of the Code and how to mix all of these functions together on my Nano.

  2. What Display I should Get, and How to Apply it to my Nano, and get it to display my counter.

  3. How to get the counter to control the Button, and output its state to the display.

  4. How to accomplish this on my Nano with as few pins as possible. (Limited Space inside the target Device.)

----> Honesty in all things… I’m a Sh_t coder, and I typically can only work from example.
But in this instance, I just cannot figure out how to put this all together.
I’ve been at this for 5 days now and I am starting to wonder if I can even do this.

Please, any help that any of you can provide would be most appreciated.

I’ve asked a few questions in Project Guidance in the past few days, but the responses are just too vague, and seem to assume that I am far more skilled in this than I am.

Nothing could be farther from the truth. Even After Days of Watching Tutorials, I just cannot seem to grasp how to put this all together.

As it sits, it appears that a combination of StateChange, BlinkWithoutDelay, Debounce, and Something Else is needed.

I just don’t know how to implement them to get to the end result.

Thank you all again for taking the time to read through this.

-Z-

zurkeyon:
Need to Interface Arduino with a device, that has 4 positions and OFF. Then cycles back to Position # 1.
So 5 button clicks Cycle the device... A Long Press Saves the ON position in case power is lost.

Let's start right at the beginning. I cannot tell from this whether the device is controlling the Arduino or if the Arduino is controlling the device? Tell us what the device is. Are the buttons on the device or are they connected to the Arduino?

AutoButtonPress = Button Automatically records a press every 24 hours, and blinks the LED for 50ms
ManualSinglePress = After a short Pause, Blinks once for 50ms
ManualDoublePress = Resets the counter to 24 Hours
ManualLongPress = After a short Pause, LED lights for 5 Seconds to SAVE home position on the original device.
OutputToSerial = Show all actions on serial console for troubleshooting purposes
OutputCounterToDisplay = Output the 24 hour countdown to a display of some kind. To see when it is reset. As well as Status.

This is also confusing. I presume the different manual presses are on the same button. This Thread (Reply #3) has a neat piece of code for different button press types.

But I don't know if there is another "autoButton", another "output to serial" button and another "output to display" button?

----> What I cannot Figure out

  1. I am having a hard time understanding the Structure of the Code and how to mix all of these functions together on my Nano.

  2. What Display I should Get, and How to Apply it to my Nano, and get it to display my counter.

  3. How to get the counter to control the Button, and output its state to the display.

  4. How to accomplish this on my Nano with as few pins as possible. (Limited Space inside the target Device.)

Make life easy for yourself and develop the program one piece at a time. Leave the display until last. Just view the output on the Serial Monitor.

Trying to plan it all at once is a recipe for a headache. Also, as your knowledge grows the solution you originally thought of might not seem suitable.

Have a look at Planning and Implementing a Program

...R

Ok,

This is the Device...
http://www.usbgear.com/SW-SATA2X4.html?pk_campaign=googleshop&gclid=CjwKEAiA1ITCBRDO-oLA-q_n8xYSJADjBQfGjvEFUxpGCBaQc7taveHhqtGnY7ktNGs9uBA5Cb09RxoCAk7w_wcB

Its a 4 Port SATA Switcher.

The Arduino, is now in control of the single Tactile Button (N.O.) on the front of the device.
So all functions must be done from that one button.
I have a Selenium Photo-Resistor, soldered to the Original Button leads on the devices mainboard. Coupled using shrink tubing to an LED, being controlled by my Arduino Nano.

A Blink of the LED, switches positions on my SATA switch.

Now that i have control of this button from the Arduino, and a Way to Trigger the original Function, I am basically passing the original button through the Nano, with the ability to use code to trigger it.

So, forgetting the display for now...

How can i setup the button, based on the above info, to do the functions mentioned in my original post?

(The Code sample you referenced looks VERY promising!)

How would I add to it an autopress every 24 hours, and a way to use the doubleclick to Reset the 24 hour timer?

If i could see how that might work i think I can use the given example to actually start to get somewhere :slight_smile:

Thank you so much!

(The Code sample you referenced looks VERY promising!)

Yes, the Jeff Salzman code is very good for what you want to do. Here is a Serial version demonstrating his code

/* 4-Way Button:  Click, Double-Click, Press+Hold, and Press+Long-Hold Test Sketch

By Jeff Saltzman
Oct. 13, 2009

http://forum.arduino.cc/index.php?topic=14479.0

To keep a physical interface as simple as possible, this sketch demonstrates generating four output events from a single push-button.
1) Click:  rapid press and release
2) Double-Click:  two clicks in quick succession
3) Press and Hold:  holding the button down
4) Long Press and Hold:  holding the button for a long time 
*/

#define buttonPin 4        // digital input pin

// Button timing variables
int debounce = 50;          // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap =500;            // max ms between clicks for a double click event
int holdTime = 2000;        // ms hold period: how long to wait for press+hold event
int longHoldTime = 5000;    // ms long hold period: how long to wait for press+hold event

// Button variables
boolean buttonVal = HIGH;   // value read from button
boolean buttonLast = HIGH;  // buffered value of the button's previous state
boolean DCwaiting = false;  // whether we're waiting for a double click (down)
boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true;    // whether it's OK to do a single click
long downTime = -1;         // time the button was pressed down
long upTime = -1;           // time the button was released
boolean ignoreUp = false;   // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false;        // when held, whether to wait for the up event
boolean holdEventPast = false;    // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already


void setup() {
   // Set button input pin
   pinMode(buttonPin, INPUT_PULLUP);
   Serial.begin(115200);
   Serial.println("Jeff Salzman Button Mult-Function Demo");
   Serial.println("http://forum.arduino.cc/index.php?topic=14479.0");
}

void loop() {
   // Get button event and act accordingly
   int b = checkButton();
   if (b == 1) Serial.println("single click");
   if (b == 2) Serial.println("double click");
   if (b == 3) Serial.println("press and hold");
   if (b == 4) Serial.println("long press and hold");
}

int checkButton() {    
   int event = 0;
   buttonVal = digitalRead(buttonPin);
   // Button pressed down
   if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
   {
       downTime = millis();
       ignoreUp = false;
       waitForUp = false;
       singleOK = true;
       holdEventPast = false;
       longHoldEventPast = false;
       if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
       else  DConUp = false;
       DCwaiting = false;
   }
   // Button released
   else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
   {        
       if (not ignoreUp)
       {
           upTime = millis();
           if (DConUp == false) DCwaiting = true;
           else
           {
               event = 2;
               DConUp = false;
               DCwaiting = false;
               singleOK = false;
           }
       }
   }
   // Test for normal click event: DCgap expired
   if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
   {
       event = 1;
       DCwaiting = false;
   }
   // Test for hold
   if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
       // Trigger "normal" hold
       if (not holdEventPast)
       {
           event = 3;
           waitForUp = true;
           ignoreUp = true;
           DConUp = false;
           DCwaiting = false;
           //downTime = millis();
           holdEventPast = true;
       }
       // Trigger "long" hold
       if ((millis() - downTime) >= longHoldTime)
       {
           if (not longHoldEventPast)
           {
               event = 4;
               longHoldEventPast = true;
           }
       }
   }
   buttonLast = buttonVal;
   return event;
}

See Nick Gammon's 'SwitchManager' for switch handing:
See Reply #1
http://www.gammon.com.au/forum/?id=11955

ZIP file for library:
http://gammon.com.au/Arduino/SwitchManager.zip

.

Using the Salzman Code,

How would I set the LED blink time length?

I dont want to just turn it on and off. I need a single button press to equal a blink of 50-100ms.

Also, How do I show you my code in the whitespace box like you are doing?

Please and thank you!

LarryD I am also looking at the examples you provided, THANK YOU AS WELL!

-Z-

Use the code tags button </>.

Show us your current sketch. Please use code tags. Use the </> icon in the posting menu. [code] Paste sketch here. [/code]

There is a ‘blink’ example in the free examples that came with your IDE.
But then look at the BWD BlinkWithoutDelay example and use its technique.

.

Ok, Here is what i have so far… Its not throwing any errors yet. So I assume I understand it for the most part, at least to this point…

I have edited some of the notation to reflect the new functions I hope to achieve.

I have the project laid out in my head as follows.
– Achieve Button Interface and States, Tied to OptoLED operation
– Establish button functions to set blink time in ms
– Establish the counter for 86400000ms
– Establish autoblink/autopress tied to counter and 5 position pattern
– Implement Display Functions

And here is the code i have so far…

//* 4-Way Button:  Click, Double-Click, Press+Hold, and Press+Long-Hold Test Sketch (Adapted For use with 4-Port SATA Switcher)

Originally By Jeff Saltzman
Modified by -Z- on:
Dec. 2, 2016

To keep a physical interface as simple as possible, this sketch demonstrates generating four output events from a single push-button.
(*Plus an interface to an existing single Tactile switch, using a standard LED and Photo-Resistor to Trigger the Switch closure.) 
1) Click:  rapid press and release, switches positions on the SATA switcher. 1-4 + ALL Off 
2) Double-Click:  two clicks in quick succession, resets 24 hour counter.
3) Press and Hold:  holding the button down (Brief), Sets the SATA Switchers on Position and Saves it to Switch Memory.
4) Long Press and Hold:  holding the button down (Long), turns the display counter on and off.
(*Added AutoPressFunction, Automatically triggers the OptoLED Every 86400000ms. The 4th triggering of the OptoLED by any source manual or auto 
 will result in a double blink of the led for 80ms each.To reset the SATA Switcher to position, and Avoid the OFF position on the switcher) 
*/

#define buttonPin 5        // analog input pin to use as a digital input
#define ledPin1 12          // digital output pin for LED 1
//#define ledPin2 4          // digital output pin for LED 2
//#define ledPin3 0          // digital output pin for LED 3
//#define ledPin4 13          // digital output pin for LED 4

// LED variables (Can change)
boolean ledVal1 = false;    // state of OPTOLED 1
//boolean ledVal2 = false;    // state of LED 2
//boolean ledVal3 = false;    // state of LED 3
//boolean ledVal4 = false;    // state of LED 4

// Constants (Will not change)
const long interval = 80;           // interval at which to blink (milliseconds)

//=================================================

void setup() {
   // Set button input pin
   pinMode(buttonPin, INPUT);
   digitalWrite(buttonPin, HIGH );
   // Set OPTOLED output pins
   pinMode(ledPin1, OUTPUT);
   digitalWrite(ledPin1, ledVal1);
   //pinMode(ledPin2, OUTPUT);
   //digitalWrite(ledPin2, ledVal2);
   //pinMode(ledPin3, OUTPUT);    
   //digitalWrite(ledPin3, ledVal3);
   //pinMode(ledPin4, OUTPUT);    
   //digitalWrite(ledPin4, ledVal4);
   Serial.begin(115200);
   Serial.println("Jeff Salzman (Originator), modified code for SATA Switcher Demo");
}

void loop() {
   // Get button event and act accordingly
   int b = checkButton();
   if (b == 1) clickEvent();
   if (b == 2) doubleClickEvent();
   if (b == 3) holdEvent();
   if (b == 4) longHoldEvent();
}

//=================================================
// Events to trigger

void clickEvent() {
   ledVal1 = !ledVal1;
   digitalWrite(ledPin1, ledVal1);
}
void doubleClickEvent() {
   ledVal1 = !ledVal1;
   digitalWrite(ledPin1, ledVal1);
}
void holdEvent() {
   ledVal1 = !ledVal1;
   digitalWrite(ledPin1, ledVal1);
}
void longHoldEvent() {
   ledVal1 = !ledVal1;
   digitalWrite(ledPin1, ledVal1);
}
//=================================================
//  MULTI-CLICK:  One Button, Multiple Events

// Button timing variables
int debounce = 20;          // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 250;            // max ms between clicks for a double click event
int holdTime = 2000;        // ms hold period: how long to wait for press+hold event
int longHoldTime = 5000;    // ms long hold period: how long to wait for press+hold event

// Button variables
boolean buttonVal = HIGH;   // value read from button
boolean buttonLast = HIGH;  // buffered value of the button's previous state
boolean DCwaiting = false;  // whether we're waiting for a double click (down)
boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true;    // whether it's OK to do a single click
long downTime = -1;         // time the button was pressed down
long upTime = -1;           // time the button was released
boolean ignoreUp = false;   // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false;        // when held, whether to wait for the up event
boolean holdEventPast = false;    // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already

int checkButton() {    
   int event = 0;
   buttonVal = digitalRead(buttonPin);
   // Button pressed down
   if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
   {
       downTime = millis();
       ignoreUp = false;
       waitForUp = false;
       singleOK = true;
       holdEventPast = false;
       longHoldEventPast = false;
       if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
       else  DConUp = false;
       DCwaiting = false;
   }
   // Button released
   else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
   {        
       if (not ignoreUp)
       {
           upTime = millis();
           if (DConUp == false) DCwaiting = true;
           else
           {
               event = 2;
               DConUp = false;
               DCwaiting = false;
               singleOK = false;
           }
       }
   }
   // Test for normal click event: DCgap expired
   if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
   {
       event = 1;
       DCwaiting = false;
   }
   // Test for hold
   if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
       // Trigger "normal" hold
       if (not holdEventPast)
       {
           event = 3;
           waitForUp = true;
           ignoreUp = true;
           DConUp = false;
           DCwaiting = false;
           //downTime = millis();
           holdEventPast = true;
       }
       // Trigger "long" hold
       if ((millis() - downTime) >= longHoldTime)
       {
           if (not longHoldEventPast)
           {
               event = 4;
               longHoldEventPast = true;
           }
       }
   }
   buttonLast = buttonVal;
   return event;
}

No time to review your sketch now, but here is an example using St. Nick’s library.

/*SwitchManager skeleton 
 
 
 This sketch is to introduce new people to the SwitchManager library written by Nick Gammon
 
 The library handles switch de-bouncing and provides timing and state change information in your sketch.
 The SwitchManager.h file should be placed in your libraries folder, i.e.
 C:\Users\YourName\Documents\Arduino\libraries\SwitchManager\SwitchManager.h
 You can download the library at:
 http://gammon.com.au/Arduino/SwitchManager.zip    Thank you Nick!
 
 In this example we have 2 normally open (N.O.) switches connected to the Arduino - increment and decrement.
 The increment switch will also be used as a "Reset" switch if pressed for more than two seconds.
 The two switches are connected between GND (0 volts) and an Arduino input pin.
 The library enables pull-up resistors for your switch inputs.
 Pushing a switch makes its pin LOW. Releasing a switch makes its pin HIGH.
 
 The SwitchManager library provides 10ms de-bounce for switches. 
 i.e. enum { debounceTime = 10, noSwitch = -1 };
 If you need more time, edit the SwitchManager.h file
 i.e. enum { debounceTime = 50, noSwitch = -1 }; //here it is changed to 50ms
 */

#include <SwitchManager.h>             
//object instantiations
SwitchManager myIncSwitch;
SwitchManager myDecSwitch;

unsigned long currentMillis;
unsigned long heartBeatMillis;
unsigned long heartFlashRate  = 500UL; // time the led will change state       
unsigned long incShortPress   = 500UL; // 1/2 second
unsigned long incLongPress    = 2000UL;// 2 seconds 
unsigned long decShortPress   = 500UL; // 1/2 second

const byte heartBeatLED       = 13;
const byte incSwitch          = 4; //increment switch is on Arduino pin 4
const byte decSwitch          = 5; //decrement switch is on Arduino pin 5

int myCounter;

//======================================================================

void setup()
{
  Serial.begin(9600);

  //gives a visual indication if the sketch is blocking
  pinMode(heartBeatLED, OUTPUT);  

  myIncSwitch.begin (incSwitch, handleSwitchPresses); 
  myDecSwitch.begin (decSwitch, handleSwitchPresses);
  //the handleSwitchPresses() function is called when a switch changes state

} //                   E N D  O F  s e t u p ( )

//======================================================================

void loop()
{
  //leave this line of code at the top of loop()
  currentMillis = millis();

  //***************************
  //some code to see if the sketch is blocking
  if (CheckTime(heartBeatMillis, heartFlashRate, true))
  {
    //toggle the heartBeatLED
    digitalWrite(heartBeatLED,!digitalRead(heartBeatLED));
  }

  //***************************
  //check to see what's happening with the switches
  //"Do not use delay()s" in your sketch as it will make switch changes unresponsive 
  //Use BlinkWithoutDelay (BWD) techniques instead.
  myIncSwitch.check ();  
  myDecSwitch.check (); 

  //***************************
  //put other non-blocking stuff here


} //                      E N D  O F  l o o p ( )


//======================================================================
//                          F U N C T I O N S
//======================================================================


//                        C h e c k T i m e ( ) 
//**********************************************************************
//Delay time expired function
//parameters:
//lastMillis = time we started
//wait = delay in ms
//restart = do we start again  

boolean CheckTime(unsigned long  & lastMillis, unsigned long wait, boolean restart) 
{
  //has time expired for this task?
  if (currentMillis - lastMillis >= wait) 
  {
    //should this start again? 
    if(restart)
    {
      //yes, get ready for the next iteration
      lastMillis = millis();  
    }
    return true;
  }
  return false;

} //                 E N D   o f   C h e c k T i m e ( )


//                h a n d l e S w i t c h P r e s s e s( )
//**********************************************************************

void handleSwitchPresses(const byte newState, const unsigned long interval, const byte whichPin)
{
  //  You get here "ONLY" if there has been a change in a switches state.

  //When a switch has changed state, SwitchManager passes this function 3 arguments:
  //"newState" this will be HIGH or LOW. This is the state the switch is in now.
  //"interval" the number of milliseconds the switch stayed in the previous state
  //"whichPin" is the switch pin that we are examining  

  switch (whichPin)
  {
    //***************************
    //are we dealing with this switch?
  case incSwitch: 

    //has this switch gone from LOW to HIGH (gone from pressed to not pressed)
    //this happens with normally open switches wired as mentioned at the top of this sketch
    if (newState == HIGH)
    {
      //The incSwitch was just released
      //was this a short press followed by a switch release
      if(interval <= incShortPress) 
      {
        Serial.print("My counter value is = ");
        myCounter++;
        if(myCounter > 1000)
        {
          //limit the counter to a maximum of 1000
          myCounter = 1000; 
        }
        Serial.println(myCounter);
      }

      //was this a long press followed by a switch release
      else if(interval >= incLongPress) 
        //we could also have an upper limit
        //if incLongMillis was 2000UL; we could then have a window between 2-3 seconds
        //else if(interval >= incLongMillis && interval <= incLongMillis + 1000UL) 
      {
        //this could be used to change states in a StateMachine
        //in this example however, we will just reset myCounter
        myCounter = 0;
        Serial.print("My counter value is = ");
        Serial.println(myCounter);
      }

    }

    //if the switch is a normally closed (N.C.) and opens on a press this section would be used
    //the switch must have gone from HIGH to LOW 
    else 
    {
      Serial.println("The incSwitch was just pushed");
    } 

    break; //End of case incSwitch

    //*************************** 
    //are we dealing with this switch?
  case decSwitch: 

    //has this switch gone from LOW to HIGH (gone from pressed to not pressed)
    //this happens with normally open switches wired as mentioned at the top of this sketch
    if (newState == HIGH)
    {
      //The decSwitch was just released
      //was this a short press followed by a switch release
      if(interval <= decShortPress) 
      {
        Serial.print("My counter value is = ");
        myCounter--;
        if(myCounter < 0) 
        {
          //don't go below zero
          myCounter = 0;
        }
        Serial.println(myCounter);
      }

    }

    //if the switch is a normally closed (N.C.) and opens on a press this section would be used
    //the switch must have gone from HIGH to LOW
    else 
    {
      Serial.println("The decSwitch switch was just pushed");
    } 

    break; //End of case decSwitch

    //*************************** 
    //Put default stuff here
    //default:
    //break; //END of default

  } //End switch (whichPin)

} //      E n d   o f   h a n d l e S w i t c h P r e s s e s ( )


//======================================================================
//                      E N D  O F  C O D E
//======================================================================

.

Unfortunately, The whole library thing looks far more complicated.

I am not even sure what a library is...

I'm sorry for my ignorance.

Trying my best. Been reading and watching tutorials for going on 6 days now :slight_smile:

Anyone have any suggestions on my code?

What direction should I go in next?

I confess I still don't understand this. It all seems very confused. It seems to be digging around in the detail without a clear concept of the system.

Am I correct to think that {A} every time you press the button on the sata switch it moves on to the next hard drive? and {B} you must hold the switch closed for 50 millisecs for it to register properly?

If that is correct then there should be a function in your program that does that - perhaps called selectNextDrive(). You can write and test that function with a short Arduino program. Then it works, and you can forget about it.

I also have the impression that you want to be able to get the Arduino to perform different sequences of selecting the next drive. I cannot understand why there is any need to have a single button for that. Having separate buttons for each activity would make for a much better user experience with a lot less chance of making a mistake - and you do NOT want to make mistakes with hard disks if the purpose is to protect your data.

...R

This unit is not intended for use by the general public. Its a managed device for IT Use.

Its meant to be a SATA cartridge Backup Drive replacement, that to a degree, takes out the human element of swapping out the drives. (Improving reliability)

The SATA switcher only supplies power to the selected Hard drive.

I can make a 4 Drive array (4 Day Backup) out of Laptop NAS Drives, and interface either e-sata hot-swap or USB3.0 hot swap, into the PC.

Then just set all the drives manually, one time in storage manager, to all come in as the same drive letter.

If the site gets hit with a malware, they have 3 days of backups that are IMPERVIOUS to Ransomware...

The Problem is getting more and more serious, and RAID, Offsite backups, and Incremental backups are ALL being hit.

There are some other mitigation strategies that we use as well, but most of the time they only work temporarily.
Eventually the Ransomware sees that its being mitigated and changes its attack sequence.

This Is something I can write a guide for, supply the code for in an instructable, and allow many of us in IT to quickly implement an inexpensive and user serviceable array for our customers and stop some of this Ransomware nonsense from seriously damaging the lives of my small business clients.

I'm tired of the standard backup strategies failing my small business customers and having business owners in my office in tears. Wondering how to put back together a decade of data.

Additionally, I can add monitoring to the device as I learn more, and watch the status from my Admin Portal.

Its something inexpensive to build for some of the limited budgets that I work with, that eventually could become a very solid solution.

I could stagger the timing between 2 of these arrays, and have an 8 day time machine, that is near bulletproof.

All programmed and in place for under 600$... Including the Drives.

As soon as I have it functional and do some testing, I'll use Sketchup to Draw up a hot Swap 4 Drive enclosure that mounts directly to the top of the SATA switch, and gives it a finished and more commercial look. Protecting the drives, while being as mechanically simple as possible.

Less to break = less to fix as time goes on.

unfortunately the SATA switcher that I was able to find that behaved in the way described above, also used a single tactile switch to accomplish saving settings and position switching.

I am simply trying to not only record the behavior of that button and interfere with it, but mimic its original operation. To avoid modifying the Sata Switcher Itself.

It is my hope that the technicians working under me, can build these and flash the finished code to them without my assistance, so we can keep everyone flexible.

We are also a small business, and anything that does not require the most expensive person in the company's full attention, saves us lots of money.

I intend to fully open source all STL files, Code that ends up getting created, and the build guide that I will Write once this is a working design.

Any assistance anyone can provide will just help me prevent more people from being victimized by this Ransomware MESS!

Thank you all in advance,

-Z-

Sounds like you're treating the symptoms but not curing the disease :wink:

Anyway, if I understand you correctly, you have one button that needs to generate a 50-100 ms pulse when pressed?

I think you have a design choice to make as to whether or not the functions called with the short, long, and double press can be blocking or not.

It's not clear to me that blocking functions(i.e.using delay()) will be an issue for you. It will certainly make for simple programming. While the LED/photoresistor pair are doing their business for 50ms or 5 seconds, what else do you see happening? There is only one led, so you cant be switching to a new drive while it is storing the settings of the last. The only other action would be a double press resetting the counter, and I don't think that a short wait by the user to do that will be bothersome.

ManualSinglePress = After a short Pause, Blinks once for 50ms
ManualDoublePress = Resets the counter to 24 Hours
ManualLongPress = After a short Pause, LED lights for 5 Seconds to SAVE home position on the original device.

Your functions would look like this

void clickEvent() {
delay(25)//short pause
digitalWrite(led, HIGH);
delay(50);
digitalWrite(led,LOW);

   
}
void doubleClickEvent() {
   //reset counter
}

void holdEvent() {
delay(25)
digitalWrite(led, HIGH);
delay(5000);
digitalWrite(led,LOW);
}

Making the functions non blocking is more complex. I would do that by having the return value of checkButton() set a boolean flag (e.g. run_clickEvent = true), make the calling of the Event conditional on that flag, and use a "blink without delay" style timer within the event function. Clear the flag when the function is complete. checkButton() and the active function will be called every pass through loop.

Seems to me the pb is windows and security of the IT of your customers... ransomware will adapt to such defense by staying silent for 5 days... then all your backups are corrupted too.

Address the pb, not displace it...

Reply #12 is long but I don't think it tells me anything I did not already know or infer.

It does not answer the questions I posed in paragraphs 2 and 4 in Reply #11

If you answer those questions I will try to help.

...R

sterretje:
Sounds like you're treating the symptoms but not curing the disease :wink:

Anyway, if I understand you correctly, you have one button that needs to generate a 50-100 ms pulse when pressed?

Unfortunately, I am not a skilled enough coder to conquer the disease in this instance.

However, I am a good enough technician\amateur engineer, to figure out how to mitigate the damage they cause :slight_smile:

And yes, a 50-100ms pulse of light is exactly what my single press should accomplish.

Double press will perform a variable reset for the counter, starting its countdown over. (No LEDs need to be lit)

Long Press (5000ms+) will perform a "Save" on the original controllers starting position. (In case of power loss, which drive we want to come up first.) This needs to be a 6000ms OptoLED pulse.

After all this, I will also write a guide in the forums here, detailing everything I have learned about interfacing with an existing switch, easy methods to accomplish it, and how to write the code for this "Pass-through" button type that I am trying to create.

Thank you for any assistance you can provide :slight_smile:

J-M-L:
Seems to me the pb is windows and security of the IT of your customers... ransomware will adapt to such defense by staying silent for 5 days... then all your backups are corrupted too.

Address the pb, not displace it...

Teaching 2000+ customers not to misbehave on the internet is MUCH more difficult than you might think...

Additionally, Ransomware can be "Silent" only as long as its "dormant" aka... Harmless.

Once it acts and starts encrypting files, there is no way for it to hide... Also no way back in the new versions.

They kill all System Restore points, Volume Shadow Copies, and Make hundreds of thousands of copies of files to prevent deep data recovery. While encrypting EVERY file they can reach out and touch... Mapped Drives, SAMBA Shares, Offsite Backups, All the incremental backup files, NAS drives... Anything they can touch.

RAID = Useless
Standard (Always Connected) Backups = Useless
Antivirus, Antimalware, Cryptoprevent = All Useless
Offsite Backups = Useless
Mitigation script that starts writing empty 000 folders/files once it detects encryption = Works for about 1-2 hours... Max

I cannot switch out 2000 Quickbooks users to Linux... Especially the Lawyers, Optometrists, Dentists, Auto shops... None of their stuff runs on anything but Windows. Unfortunately.

So, I am forced to find a solution that a malware/ransomware CANNOT defeat. Such as a powered off drive. Not Physically connected to the system. And IF I do expose the Arduino for live reprogramming (Unlikely), it will have a password interface in front of it with a 23 character strong out front.

And even IF they manage to silently infect the other drives, the code cannot run until the drive is again exposed to a windows system.

Once I see the infect, I can LOCK the current drive into place on the SATA switch (Key function on the front does this) and prevent it from switching the other drives back on, until I can do a linux data recovery and scrub...

Its the Least complex, least expensive, easiest for my Jr. Techs to replicate, solution that I can come up with.

Its all just a matter of code now. I pretty much have it built sitting here next to me on my bench.

:slight_smile:

Robin2:
Am I correct to think that {A} every time you press the button on the sata switch it moves on to the next hard drive? and {B} you must hold the switch closed for 50 millisecs for it to register properly?

I also have the impression that you want to be able to get the Arduino to perform different sequences of selecting the next drive. I cannot understand why there is any need to have a single button for that. Having separate buttons for each activity would make for a much better user experience with a lot less chance of making a mistake - and you do NOT want to make mistakes with hard disks if the purpose is to protect your data.

...R

I apologize, It was late and I was struggling to keep from passing out at the keys. Guess I started type-rambling.

A: Yes When pressed the original switch moves through the 4 drive positions, with a 5th position, that shuts off ALL drives. (I will be putting in code to try and avoid this position. I never want the drives all OFF)
B: I am testing 50-100ms for holding it closed, both seem to work. So yes, somewhere in there.

I want the Arduino to Mirror the Functions of the Original Button on the Device. Exactly.
Plus add the double click function to the same button, to reset the countdown timer and display.

I am simply trying to interface with the button for the Auto-press, counter, and adding a display.

But if it seriously complicates life, I am sure I can add a reset button to the Design and connect it to another Arduino pin. But i am also not sure how many pins I'll need for the display.

I apologize again for the rambling. I didn't even realize that the ramble wasn't even answering the questions.

Thank you for taking the time to help me :slight_smile: