Arduino reading voltage issues.

I am testing a wire and counting the amount of cycles it can be bent at 180 degrees. When the wire is broken and stops providing the 120vac I have a continuity device that will no longer output 5v to my output pin. The issue I am having is that sometimes the arduino thinks the 5v is not being output from the continuity module so the program stops. Other times when the 120vac is not being applied, the program takes up to 100 seconds to actually stop. Are there issues with my code?

Code here:

#include <SD.h>
#include <Button.h>
#include <SPI.h>

File myFile;
int output1 = 3;
int SDcard = 10;
long counter = 0;
int supply1 = 8;
int input1 = 5;
long duration = 0;
int startDelay = 5000;




// the setup routine runs once when you press reset:
void setup() {

  Serial.begin(9600);

  pinMode(supply1, OUTPUT);
  digitalWrite(supply1, HIGH);
  //digitalWrite(input1, HIGH);
  pinMode(output1, OUTPUT);
  delay(startDelay);
  int x = millis();

  Serial.println("Initializing SD card...");
  pinMode(SDcard, OUTPUT);

  if (!SD.begin(SDcard)) {
    Serial.println("Intialization failed");
    return;
  }

  Serial.println("initialization complete!");



}//end of setup


// the loop routine runs over and over again forever:
void loop() {

  digitalWrite(output1, HIGH);
  counter++;
  String counterString = String(counter);
  counterString.concat(" cycles");

  delay(1000);
  Serial.println(counterString);
  digitalWrite(output1, LOW);
  counter++;
  counterString = String(counter);
  counterString.concat(" cycles");

  delay(1000);
  Serial.println(counterString);

  if (digitalRead(input1) != HIGH) {
    digitalWrite(input1, LOW);
    digitalWrite(output1, LOW);
    digitalWrite(supply1, LOW);

    myFile = SD.open("round.csv", FILE_WRITE);

    
    duration = millis() - startDelay; //duration in milliseconds (had to subtract the 3000 millisecond setup)
    int h = duration / 3600000;
    long remainder = (duration % 3600000);
    int m = remainder / 60000;
    long newRemainder = remainder % 60000;
    int s = newRemainder / 1000;
    long newNewRemainder = newRemainder % 1000;
    int ms = newNewRemainder;

    Serial.println("Cycle duration:");
    Serial.print(h);
    Serial.print(":");
    Serial.print(m);
    Serial.print(":");
    Serial.print(s);
    Serial.print(" (hh:mm:ss) ");
    Serial.println(duration);
    Serial.println("aborting test, power has been lost");
    Serial.print("Writing to file...");

    if (myFile) {
      myFile.print(" ");
      myFile.print(",");
      myFile.print(h);
      myFile.print(":");
      myFile.print(m);
      myFile.print(":");
      myFile.print(s);
      myFile.print(",");
      myFile.println(counterString);
      Serial.println("Writing is complete");
      myFile.close();
    }
    else {
      Serial.println("round write failed");
    }

    delay(2000);
    while (1) {
      
      Serial.print("round testing is complete, there were ");
      Serial.println(counterString);
      delay(3600000);
    }//infinite loop when testing is complete

  }//end of if
}//end of loop

If the pin 'input1' is an input, then set is as input with pinMode() and don't digitalWrite() to it. Or do you want to turn the pullup resistor on and off ? why ? How is the hardware ? Could there be noise on that 5V signal ? Perhaps a ground problem ? Perhaps a number of samples should be taken, to eliminate spikes and noise. An optocoupler would be the best choice. It is also possible to check the input with analogRead(), and decide at what voltage level the wire is broken.

Could you name all pins with the word "pin" ? Like "pinSupply1" and "pinInput1" or "supply1Pin" and "input1Pin" and so on.

I didn’t use pinMode for the input pin because the arduino documentation states that pinMode(pin,INPUT) allows for the pin to pick up noise easier. Also, the digital write to the input pin is commented and is only used for testing without our wire bending.

Also, when I set that input pin HIGH manually it never stops. The module that outputs the 5v signal always has a strong signal. It never attracts noise or anything so I can't figure out the issue.

If you need a pin to be an input, you set it as input with pinMode(). Increasing noise or whatever is not true. A digital pin can be INPUT or INPUT_PULLUP or OUTPUT HIGH or OUTPUT LOW. Only those four things, nothing else. One of the writes to input1 is commented out, but the other one is not.

A digital input can not be set HIGH with digitalWrite() to test it. Writing a HIGH to an input will enable the internal pullup resistor. That is a special feature of the ATmega chip. Are you perhaps familiar with PIC chips ? The AVR chips differ in many ways.

The use of input1 doesn't have to be the problem, but I want the basics of the sketch fixed, before trying to find the cause of the problem.

Here is what I have. The issue still stands:

#include <SD.h>
#include <Button.h>
#include <SPI.h>

File myFile;
int outputPin1 = 3;
int SDcard = 10;
long counter=0;
int supplyPin1 = 8;
int inputPin1 = 5;
long duration = 0;
int startDelay = 5000;

  
  

// the setup routine runs once when you press reset:
void setup() { 
  
  Serial.begin(9600);

  pinMode(supplyPin1, OUTPUT);
  digitalWrite(supplyPin1,HIGH);
//digitalWrite(inputPin1, HIGH);//testingCD
  pinMode(outputPin1, OUTPUT);
  pinMode(inputPin1,INPUT);  
  delay(startDelay);
  int x = millis();
  
  Serial.println("Initializing SD card...");
  pinMode(SDcard, OUTPUT);
  
  if (!SD.begin(SDcard)){
  Serial.println("Intialization failed");
  return; 
  }
  
    Serial.println("initialization complete!");
 
  
  
}//end of setup


// the loop routine runs over and over again forever:
void loop() {
  
   digitalWrite(outputPin1, HIGH);
   counter++;
   String counterString = String(counter);
   counterString.concat(" cycles");
     
   delay(1000);  
   Serial.println(counterString);   
   digitalWrite(outputPin1, LOW); 
   counter++;
   counterString = String(counter);
   counterString.concat(" cycles");  
    
   delay(1000);              
    Serial.println(counterString);

   if(digitalRead(inputPin1) != HIGH){
      digitalWrite(inputPin1,LOW);
     digitalWrite(outputPin1,LOW);
     digitalWrite(supplyPin1,LOW);
     myFile = SD.open("flat.csv", FILE_WRITE);
     
     
     duration = millis()-startDelay;//duration in milliseconds (had to subtract the 3000 millisecond setup)
     int h = duration/3600000;
     long remainder = (duration%3600000);
     int m = remainder/60000;
     long newRemainder = remainder%60000;
     int s = newRemainder/1000;
     long newNewRemainder = newRemainder%1000;
     int ms = newNewRemainder;
     
     Serial.println("Cycle duration:");
     Serial.print(h);
     Serial.print(":");
     Serial.print(m);
     Serial.print(":");
     Serial.print(s);
     Serial.print(" (hh:mm:ss) ");
     Serial.println(duration);
     Serial.println("aborting test, power has been lost"); 
     Serial.print("Writing to file...");
     
     if (myFile){
     myFile.print(" ");
     myFile.print(",");
     myFile.print(h);
     myFile.print(":");
     myFile.print(m);
     myFile.print(":");
     myFile.print(s);
     myFile.print(",");
     myFile.println(counterString);
     Serial.println("Writing is complete");
     myFile.close();
     }
     else{Serial.println("round write failed");
   }
     
     delay(2000);                                                                                                                                                                                
     while(1){
       Serial.print("flat testing is complete, there were ");
       Serial.println(counterString);
       delay(3600000);
    }//infinite loop when testing is complete
    
   }//end of if

}//end of loop

Please remove the line that is commented out that writes to the inputPin1, unless you want to enable the internal pullup resistor someday. If you do you should use pinMode with INPUT_PULLUP.

The "int x = millis() ;" is not used. You can remove that line. If you want to do something with millis() later on, always use 'unsigned long' with millis().

It is not needed to make SDcard an output, since "SD.begin()" initializes that pin. Is it a logging shield with SD socket ? or an Ethernet Shield ? If it is an Ethernet Shield, you have to disable the W5100 chip which uses also the SPI bus.

Please do not write to inputPin1. Search for "inputPin1" to see where it is used.

The "duration = millis() - startdelay;" has a rollover problem and variable size mismatch. The startdelay is an integer, that could cause strange results. The duration is a 'long' that causes a rollover problem. The code is wrong, since 'startdelay' could be higher than millis(), that way the rollover problem can not be avoided.

Perhaps the input voltage is not a good 0V or 5V as you think it is :smiley_cat: I prefer to add a debounce, or a hardware RC filter, or software filter, or some extra check.

Some of use avoid the 'String' object, because of memory fragmentation. In your sketch, avoiding the 'String' object is easy.

...

void loop() {

  digitalWrite(outputPin1, HIGH);
  counter++;

  delay(1000);
  Serial.print(counter);
  Serial.println(" cycles");
  digitalWrite(outputPin1, LOW);
  counter++;

  delay(1000);
  Serial.print(counter);
  Serial.println(" cycles");
  ...

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks, so we can see how you have the input and power supplies wired.

Tom... :)

I made the changes you’ve told me to, except I’m not sure the best way to debounce. Maybe that could be the issue. Also, I can’t figure out another way to write to the SD. However, I have noticed that writing doesn’t always occur. It is strange. Right now I am trying to write to round.csv and it won’t write anymore but if I and write to test.csv it writes to that file fine.

I know you say that maybe the signal isn’t strong but even when I am supplying no signal the arduino somehow is getting voltage to cycle for up to ~100 cycles. I feel as if the issue is related to the arduino itself. Below are documents, code and my circuit.

Updated code:

#include <SD.h>
#include <SPI.h>

File myFile;
int output1 = 3;
int SDcard = 10;
long counter = 0;
int supply1 = 8;
int input1 = 5;
unsigned long duration = 0;
unsigned long startDelay = 5000;




// the setup routine runs once when you press reset:
void setup() {

  Serial.begin(9600);

  pinMode(supply1, OUTPUT);
  digitalWrite(supply1, HIGH);
  pinMode(output1, OUTPUT);
  delay(startDelay);

  Serial.println("Initializing SD card...");
  pinMode(SDcard, OUTPUT);

  if (!SD.begin(SDcard)) {
    Serial.println("Intialization failed");
    return;
  }

  Serial.println("Initialization complete!");



}//end of setup


// the loop routine runs over and over again forever:
void loop() {

  digitalWrite(output1, HIGH);
  counter++;

  delay(1000);
  Serial.print(counter);
  Serial.println(" cycles");
  digitalWrite(output1, LOW);
  counter++;

  delay(1000);
  Serial.print(counter);
  Serial.println(" cycles");

  if (digitalRead(input1) != HIGH) {
    digitalWrite(output1, LOW);
    digitalWrite(supply1, LOW);

    myFile = SD.open("round.csv", FILE_WRITE);

    
    duration = millis() - startDelay; //duration in milliseconds (had to subtract the 3000 millisecond setup)
    int h = duration / 3600000;
    unsigned long remainder = (duration % 3600000);
    int m = remainder / 60000;
    unsigned long newRemainder = remainder % 60000;
    int s = newRemainder / 1000;
    unsigned long newNewRemainder = newRemainder % 1000;
    int ms = newNewRemainder;

    Serial.println("Cycle duration:");
    Serial.print(h);
    Serial.print(":");
    Serial.print(m);
    Serial.print(":");
    Serial.print(s);
    Serial.print(" (hh:mm:ss) ");
    Serial.println(duration);
    Serial.println("aborting test, power has been lost");
    Serial.print("Writing to file...");

    if (myFile) {
      myFile.print(" ");
      myFile.print(",");
      myFile.print(h);
      myFile.print(":");
      myFile.print(m);
      myFile.print(":");
      myFile.print(s);
      myFile.print(",");
      myFile.println(counter);
      Serial.println("Writing is complete");
      myFile.close();
    }
    else {
      Serial.println("round write failed");
    }

    delay(2000);
    while (1) {
      
      Serial.print("round testing is complete, there were ");
      Serial.print(counter);
      Serial.println(" cycles");
      delay(3600000);
    }//infinite loop when testing is complete

  }//end of if
}//end of loop

Circuit: http://postimg.org/image/iglstx7nb/

IACM-5 Datasheet: http://www.farnell.com/datasheets/1046708.pdf

Relay Datasheet: http://www.clare.com/home/pdfs.nsf/0/7B8386C9F64F3F47852572810042EE06/$file/CPC1218.pdf

SD card Breakout board: http://www.adafruit.com/products/254

Thanks for the info.

The SD module is made to work with 5V, that is very good :)

Why is the mains detector is wired like that ? Connect 120VAC to pin 1 and 2 inputs. That is okay. Pin 3 +5V : I would connect that to Arduino 5V. Pin 4 OUTPUT : connected to pin 8, and use INPUT_PULLUP or an extra pullup resistor of 10k. Pin 5 COMMON : I would connect that to Arduino GND.

The way you use millis() is not okay.

What about the power for the Micro board ? Can you measure the 5V pin ? It should not be 4.5V or lower. If the 5V voltage is okay, could you try an example that only writes a file ? Perhaps that SD card is not compatible.

Do you use an optomos relay to read a switch ? I don't understand.

I am testing the bending of a 120Vac wire. The 120Vac goes into the IACM-5 which is used to detect the continuity of the 120Vac wire. If the IACM-5 no longer receives the 120Vac, the IACM-5 will no longer output 5V. The 5V from the IACM-5 goes to the pin, inputPin1, on the arduino. My code is written to detect if that pin is HIGH or LOW. I am also using the arduino to send a 5Vdc signal to the relay (5Vdc to 24Vdc). The relay uses the 5Vdc signal to control the 24Vdc pneumatic device. The pneumatic device is responsible for the bending of the 120Vac wire.

The SD card must be compatibile if I can write to one file on the card fine, but the other does not work.

As for the INPUT_PULLUP did you mean pin 6 rather than pin 8? I have tried to wire the IACM-5 as you have stated before and it didn't do what I wanted. I may have done the PULLUP wrong though.

I had the IACM-5 wired up the way I posted because when 120Vac is running through the wire the IACM-5 outputs ~4V-5V. If the wire is unplugged it drops the voltage ~0. This is what I want.

The board is getting 5.02Vdc when measured.

How can I fix my millis()?

chadwell1028:
As for the INPUT_PULLUP did you mean pin 6 rather than pin 8?
I have tried to wire the IACM-5 as you have stated before and it didn’t do what I wanted. I may have done the PULLUP wrong though.

I had the IACM-5 wired up the way I posted because when 120Vac is running through the wire the IACM-5 outputs ~4V-5V. If the wire is unplugged it drops the voltage ~0. This is what I want.

The board is getting 5.02Vdc when measured.

How can I fix my millis()?

Chadwell1028,
I would recommend these changes:

  • add a 120v load that uses the wire under test (a light bulb)
  • on the IACM-5 connect vcc to Arduino 5V+
  • connect IACM-5 output to Arduino pin A0, Connect a 4.7k resistor from A0 to 5v+
  • connect IACM-5 common to Arduino GND
  • add this to setup()
    pinMode(A0,INPUT_PULLUP);
    I recommend using an Analog Input, you will be able to see the
    degradation of the cable while it is failing.
  • make a testing() function that handles overflow of the millis() counter.
bool testingdone(unsigned long * overFlowMS,unsigned long *startMS, int *voltage){

if (millis()<*startMS){// millisecond counter overflowed
   *overFlowMS= 0xFFFFFFFF - *startMS;
   *startMS=0;
   }

bool result=false;

// you can average a few readings to stabilize the output
long totalvoltages=0
for(uint8_t i=0;i<10;i++){
  delay(10);
  totalVoltages = totalVoltages +analogRead(A0);
  }
int a = totalVoltage / 10;

if (a<920){ // voltage on A0 less than 4.5v, this number is (ADC_resolution / 5v)*4.5V
   // the UNO has a 10bit ADC 920~ (1024/5)*4.5.  Actually 921.6
    result = true;
   }
*voltage = a;
return result;
}

unsigned long startMS=0, overFlowMS=0;

void loop(){
// setup delay

startMS=millis();
unsigned long flexCount=0;
int failVoltage=0,priorVoltage=0;

while(!(testingDone(&overFlowMS,&startMS,&failVoltage)){
   //bend cable
   flexCount++;
   if(abs(priorVoltage - failVoltage))> significant_delta){
     //write failVoltage to file
     priorVoltage = failVoltage;
     }
   // delay to allow motion to complete
 }
// write to file
unsigned long duration = overFlowMS + millis()-startMS;
// maximum testing period is 1176+ hours. 49 days.

// test termination code

}

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560’s. It adds 1MB of RAM for those projects where 8KB is not enough.

Chuck,

Where would I call the testing() function?

I would also like to move toward Peter's proposed solution first.

chadwell1028: Chuck,

Where would I call the testing() function?

Review the code, I included an example Loop() that shows usage.

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.