Help me finalize my prototype :-(

Hi guys! (Sorry for my English)

Been strugging for quite a while, to get my (Dont know exact English word) "Meter Wheel Counter" to work correctly.

Basically (I strongly advice you to check out the attached image for graphical explanation) my prototype must be able to measure the cable length going through a "block" (used in Marine equipment to support the cables bending). I guess in some way, you could compare the function of my prototype with a speed-o-meter found in cars.

So far my prototype is able to count up and down, depending if the "block" is rolling forward or backwards (= Scientific cable is being pulled in or out) - but my real problem is this:

I cannot get my display to show the correct meter/minute (= how fast the cable is being rolled in or out from cable-winch). I've tried tons of examples, but none are close to my solution, so I've excluded it from my code below.

I'm sure some of you pros can fix it super fast :slight_smile: - and yes, I know my way of writing code can seem strange. I'm still learning :slight_smile: .. Hope you also can live without comments in code (I've got my own comments in Danish, in another sketch)

Code:

//***********************************************************************************************
#include <SoftwareSerial.h> 
#include <Streaming.h>  
//***********************************************************************************************
int sensor1 = 2;  // Magnetsensor 1 input
int sensor2 = 3;  // Magnetsensor 2 input

float sensor_count = 0.00;
int sensor_last_value = LOW;
int n = HIGH;

float inner_cable_distance; 
float display_cable_rollout;  

#define txPin  7       
#define rxPin 255       

#define inverted 1      // Inverted serial (like RS-232, but TTL)
#define noninverted 0   // Noninverted serial (like UART output)
#define SPOL inverted
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin, SPOL);
#if SPOL
#define STOPBIT LOW  // For inverted serial, the output pin must be LOW when data is not being sent; for noninverted, HIGH.
#else
#define STOPBIT HIGH
#endif

#define CLS (char) (0x0C)  
#define MOVETO (char) 16   
#define LABEL0 (char) (0x0C)   
#define LABEL1 (char) (32+64)  
#define LABEL2 (char) (48+64)  
#define LABEL3 (char) (41+64)  
#define LABEL4 (char) (16+64)  
//***********************************************************************************************
void setup() { 
    
    delay(500) ; 
    digitalWrite(txPin, STOPBIT);  
  
    mySerial.begin(9600);             // Set the communication data rate for the display. 
    mySerial.write(0x0C);             // Clear screen
    
    attachInterrupt(0, sensor_counter, CHANGE);  
    attachInterrupt(1, sensor_counter, CHANGE);  
    
    mySerial.write(0x0C);
    mySerial <<MOVETO <<LABEL0 <<"Magnetdist. 65cm";   //trying out serial text Streaming.
    mySerial <<MOVETO <<LABEL1 <<"Meter =";         
    mySerial <<MOVETO <<LABEL2 <<"M/min ="; 
    
}
//***********************************************************************************************
void sensor_counter ()  
{
  n = digitalRead(sensor1);
  if ((sensor_last_value == HIGH) && (n == LOW)) 
  {
    if (digitalRead(sensor2) == LOW)           
    {
      sensor_count = sensor_count + 1;         
    } 

    else
    {
      sensor_count = sensor_count - 1; 
    }
      inner_cable_distance = sensor_count * 0.65;
      display_cable_rollout = inner_cable_distance;
    }

  sensor_last_value = n;
}
//***********************************************************************************************
void loop() 

  { 
    mySerial.write(16); // Experimenting with alternative to serial Streaming
    mySerial.write(45+64); 
    mySerial.write(0x12); 
    mySerial.write(0x35); 
    mySerial.print(display_cable_rollout); 
  }
//***********************************************************************************************

float sensor_count = 0.00;

The number of times that a magnet has passed the sensor is an integer. A magnet can not have passed 3.7 times.

The magnet either passed or it didn't.

    attachInterrupt(0, sensor_counter, CHANGE);  
    attachInterrupt(1, sensor_counter, CHANGE);

Why? Connecting the sensor to one of the pins is sufficient. Each time the sensor sends a pulse, both interrupt pins will see the rising edge and the falling edge, so sensor_counter will be called 4 times for each pulse.

It would be better to feed the signal into both pins, but have two different interrupt handlers. One should deal with the RISING edge and one should deal with the FALLING edge.

  if ((sensor_last_value == HIGH) && (n == LOW))

There does not appear to be a relationship between sensor_last_value and n. There would appear to be a relationship between sensor_last_value and sensor_curr_value. Use names that make it clear what you are comparing. n might be easier to type, but it doesn't mean anything. One letter names are fine as loop indexes. But, nowhere else.

Finally, variables used in the interrupt service routine AND in loop() (or setup()) must be declared volatile. display_cable_rollout is one variable that is used in the ISR and in loop(), but is not declared volatile.

Sorry, not to butt in, but what does declaring something volatile do?

what does declaring something volatile do?

Look at the variable from the point of view of the loop() function. Nothing in the loop() function changes the value in the memory location that display_cable_rollout occupies. So, once the value has been fetched once, the loop() function doesn't know that the value can change, so it never sees a need to fetch the value again.

The volatile declaration tells the loop() function that the can be changed outside of loop()s control, so loop() knows that it needs to fetch the value every time.

That's a gross simplification of the way the code that is generated actually works, but that's the reason that different machine instructions are generated.

That's really cool. Thanks for taking the time to write that out.

Hi everyone.

Thanks for taking your time helping me out and giving advice - I'm learning something every day :slight_smile:

BUT - don't know if it would be too much to ask, if someone would try and make an code-example (solution) for my problem?

Then I'd be REALLY grateful :slight_smile:

Have a nice Friday :slight_smile:

-marengsen

BUT - don't know if it would be too much to ask, if someone would try and make an code-example (solution) for my problem?

It isn't really clear what your problem is. You have a fundamental flaw in the program in that display_cable_rollout is not declared volatile. Until you correct that, and test the changed code, you can not be sure what your problem is. And, since you can't be, neither can we.

Your approach to reading the interrupts looks flawed to me, too. But whether your approach will work, or not, we won't know until you've tested again after fixing the problem with the non-volatile variable.