Light Sensing Test Fixture Program

First off, let me give a little bit of information about my situation and what I'm trying to accomplish with this project. I'm a mechanical engineering intern working to create a test fixture to evaluate prototype components for repeated use/longevity. The only coding experience I had before starting this project was with Matlab, so nothing as intensive as C/C++. The test fixture uses some solenoid-valves to operate four pneumatic linear actuators that press buttons or tilt components back and forth to simulate use. The solenoids are turned on and off using a Seeed Relay Shield V2 that I have attached to an Uno R3. So far I've developed enough of an understanding of coding to cobble together a sketch that can trigger all four relays at their predetermined cycling rates. Here it is:

// These variables store the flash pattern
// and the current state of the LED

int ledPin1 =  7;      // the number of the LED pin
int ledState1 = LOW;             // ledState used to set the LED
unsigned long previousMillis1 = -750;        // will store last time LED was updated
long OnTime1 = 250;           // milliseconds of on-time
long OffTime1 = 750;          // milliseconds of off-time

int ledPin2 =  6;      // the number of the LED pin
int ledState2 = LOW;             // ledState used to set the LED
unsigned long previousMillis2 = -1000;        // will store last time LED was updated
long OnTime2 = 1000;           // milliseconds of on-time
long OffTime2 = 1000;          // milliseconds of off-time

int ledPin3 =  5;      // the number of the LED pin
int ledState3 = LOW;             // ledState used to set the LED
unsigned long previousMillis3 = 0;        // will store last time LED was updated
long OnTime3 = 1000;           // milliseconds of on-time
long OffTime3 = 1000;          // milliseconds of off-time

int ledPin4 =  4;      // the number of the LED pin
int ledState4 = LOW;             // ledState used to set the LED
unsigned long previousMillis4 = -990;        // will store last time LED was updated
long OnTime4 = 10;           // milliseconds of on-time
long OffTime4 = 1990;          // milliseconds of off-time

void setup() 
{
  // set the digital pin as output:
  pinMode(ledPin1, OUTPUT);      
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
}

void loop()
{
  // check to see if it's time to change the state of the LED
  unsigned long currentMillis = millis();

  if((ledState1 == HIGH) && (currentMillis - previousMillis1 >= OnTime1))
  {
    ledState1 = LOW;  // Turn it off
    previousMillis1 = currentMillis;  // Remember the time
    digitalWrite(ledPin1, ledState1);  // Update the actual LED
  }
  else if ((ledState1 == LOW) && (currentMillis - previousMillis1 >= OffTime1))
  {
    ledState1 = HIGH;  // turn it on
    previousMillis1 = currentMillis;   // Remember the time
    digitalWrite(ledPin1, ledState1);  // Update the actual LED
  }
  
  if((ledState2 == HIGH) && (currentMillis - previousMillis2 >= OnTime2))
  {
    ledState2 = LOW;  // Turn it off
    previousMillis2 = currentMillis;  // Remember the time
    digitalWrite(ledPin2, ledState2);  // Update the actual LED
  }
  else if ((ledState2 == LOW) && (currentMillis - previousMillis2 >= OffTime2))
  {
    ledState2 = HIGH;  // turn it on
    previousMillis2 = currentMillis;   // Remember the time
    digitalWrite(ledPin2, ledState2);  // Update the actual LED
  }
  
  if((ledState3 == HIGH) && (currentMillis - previousMillis3 >= OnTime3))
  {
    ledState3 = LOW;  // Turn it off
    previousMillis3 = currentMillis;  // Remember the time
    digitalWrite(ledPin3, ledState3);  // Update the actual LED
  }
  else if ((ledState3 == LOW) && (currentMillis - previousMillis3 >= OffTime3))
  {
    ledState3 = HIGH;  // turn it on
    previousMillis3 = currentMillis;   // Remember the time
    digitalWrite(ledPin3, ledState3);  // Update the actual LED
  }
  
  if((ledState4 == HIGH) && (currentMillis - previousMillis4 >= OnTime4))
  {
    ledState4 = LOW;  // Turn it off
    previousMillis4 = currentMillis;  // Remember the time
    digitalWrite(ledPin4, ledState4);  // Update the actual LED
  }
  else if ((ledState4 == LOW) && (currentMillis - previousMillis4 >= OffTime4))
  {
    ledState4 = HIGH;  // turn it on
    previousMillis4 = currentMillis;   // Remember the time
    digitalWrite(ledPin4, ledState4);  // Update the actual LED
  }
}

The reason the variables are named as led's is because I tested my code in 123D circuits using led's as visual analogues for the relays while I waited for my components to arrive in the mail. I've since tested the sketch on my actual components and it runs just fine.

Here is where things get interesting. In addition to actuating these buttons, the test fixture must also make sure that the equipment attached to the buttons actually functions when the buttons are pressed. In this case, the two buttons are attached to their own respective lights. What I am attempting to do is use two light sensors (Adafruit TSL2591's) to sense when each light is on or off. If the light is off when it is supposed to be on, or on when it is supposed to be off, the test fixture should be able to recognize this and stop the test, while also noting which test cycle the failure occurred at.

I have some ideas on how I think this could work, but as I said before, I have almost zero experience writing code so I'm at a loss on how to implement my ideas. Mainly I was thinking of finding benchmarks for light levels when the lights are on and off. The program can then check if the light level is above or below the levels and determine if the light is truly on or off. Using this information as a variable, I would then add a condition to my current code in my if statements that if the sensor does not match the expected state, to end the test and print what cycle the test was on. I based this idea on the examples provided by Adafruit on their website (https://learn.adafruit.com/adafruit-tsl2591/wiring-and-test) under the section titled "void getEvent(sensors_event_t*)".

My next issue is interpreting the data coming in from the TSL2591. So far I've only played around with the example sketch that provides a continually updating readout in the serial monitor. My goal is to have the program check the sensor value only when the if statement requires a reading to make a decision, but I don't know how to go about meshing the code for getting this reading with the code to create the output.

I wish I could be more specific in my questions, but as you can probably tell I'm in way over my head here with how little experience and knowledge of programming I have. Basically what I'd like to know is if my goals are realistically attainable, if what I have started so far makes sense considering the rest of the project, and what paths I should look down to get this completed. Any other suggestions for improvement or other methods of creating this program are both welcomed and appreciated. If there's any other information I left out that could help you to help me, please don't hesitate to ask. Thanks in advance for any help.

The reason the variables are named as led’s is because I tested my code in 123D circuits using led’s as visual analogues for the relays while I waited for my components to arrive in the mail. I’ve since tested the sketch on my actual components and it runs just fine.

That’s the history, not the reason. Change the names to reflect what they really mean.

Basically what I’d like to know is if my goals are realistically attainable,

Yes.

if what I have started so far makes sense considering the rest of the project

Yes.

and what paths I should look down to get this completed.

I think that the hardest part is going to be determining what the sensors should be reading, for any given test step. I think I’d create a file on a SD card, and read that file, to get the expected readings, test number, actuator positions, etc. to know what to do/expect. Then, do it, and see if you get the expected results.

Thanks for the reply. I'll change those variable names to reflect their more permanent use. As for the SD card idea, I have a couple questions. Is the main reason to have the SD card simply because it saves space on the Arduino to run the actual program? What type of hardware would be required to interface the card and the Arduino? It is good that you bring up the possibility of multiple test setups, as that is something I forgot to mention earlier. For some tests the fixture will be in regular room temperature conditions in a regular lab environment, while other tests will be run in a thermally variable test chamber, which will have different lighting conditions I'm sure.

I have a couple questions. Is the main reason to have the SD card simply because it saves space on the Arduino to run the actual program?

No, it's because the code should not define the test. Adding a test setup, or changing a test setup, if the code defines the test, requires a code change. If the text file defines the test setup and results, adding a test, or changing one, means changing the text file and restarting the Arduino - no code change needed.

What type of hardware would be required to interface the card and the Arduino?

Just an SD card reader shield. The Ethernet shields usually include an SD reader(, and you could then post the results to the web 8)).

Another shield huh? I guess I’ll have to revise and reprint my custom enclosure, shucks :wink: (picture attached). Continuing along with the SD card idea, how does one handle the data coming from the SD into the Arduino? After reading the example on SD Read/Write it’s my understanding that I would still create the variables in the sketch, but store their values in the .txt file on the card. If there are multiple variables that are getting their values from the same file, there is obviously some way to make sure each variable is assigned the correct value from those stored in file. What then is the best format for the data on the card for ease of importing and variable assignment? I apologize if my questions are overly basic, I’m trying to look things up as I go so as to not ask for a personal response when information is already available, but with some of this I’m not even sure what I should be searching for to get where I need to be. Thanks again for your help and patience.

I guess I'll have to revise and reprint my custom enclosure, shucks

I have this mental image of you trying to hitch a cart to a horse...

Continuing along with the SD card idea, how does one handle the data coming from the SD into the Arduino?

Carefully.

After reading the example on SD Read/Write it's my understanding that I would still create the variables in the sketch, but store their values in the .txt file on the card.

Yes.

If there are multiple variables that are getting their values from the same file, there is obviously some way to make sure each variable is assigned the correct value from those stored in file.

You'd read an entire record, assuming that each record contains all the data for one setup, and then parse the stored data. Deal with each token, converting the string token to the appropriate type, storing in the appropriate place.

You could store the data in the file without any identifiers, and assume that all records contain the same number of tokens in the same order. That's easy. Relatively, anyway.

Or you could store the data in name=value form. Then, during parsing, you'd get the name of the variable to store the data in, followed by the data to store in the variable. While that, at first glance, sounds easier, variable names in the executing sketch do not exist. Only addresses do, and they can not be known in advance nor can they be assumed to be the same every time. So, you need to match the name you know at run time to the address that the compiler generated:

if(strcmp(name, "RotAngle") == 0)
   RotAngle = atoi(value);

What then is the best format for the data on the card for ease of importing and variable assignment?

I think I've covered that.

I apologize if my questions are overly basic,

They are not.

Thanks again for your help and patience.

You're welcome.