Same setup, two different versions of code. Trying do debug sensing on A(n).

First post = )

Hi,

This is my first attempt to use Arduino for something.

I use Arduino (UNO) one relay shield and one analog input, connected "all that" to my appartment interphone system.

The interphone system is two wire and not much of importance because the issue is not there I beleive but in the code.

Basically I have "attached" GND and A(0) to interphone speaker.
When interphone is IDLE voltage over speaker connection is ZERO. No activity intended in this state.

Second case (state) is when interphone is ringing the voltage on speaker connections is between 0.8 - 1.4 volts. At that moment arduino closes the relay and my building gate is opening for a delay(n).

Here is the code that is working as intended. I know that not all cases are covered but this works pretty fine for a few days now. I ring and then building door lock is open.

void setup()
{ 
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
  delay(1000);
  digitalWrite(4, LOW);
  delay(1000);
} 
 
void loop()
{
  int voltage = analogRead(A1);
  if (voltage > 60)
  {
    delay(3000);
    digitalWrite(4, HIGH);
    delay(6000);
    digitalWrite(4, LOW);
  }
}

I have a testing mechanism which is: When I lift a interphone "speaker and mic handle" the voltage is also present on the speaker. Then I close the handle and Arduino is opening the door again.

This way I can confirm that my code is working without going DOWN UP from 5th floor.

My issue is that when I upload this second version of code. It works only partially.
When I do the test with interphone handle everything is just fine.

But with the second version the actuall ringing from interphone button downstairs Arduino won't let me in. I am clueless how to debug this.

This is NOT working code. Please don't mind the Serial.println garbage.

void setup() {
  Serial.begin(9600);
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
  delay(1000);
  digitalWrite(4, LOW);
  delay(1000);
}

unsigned long ringstart;
unsigned long ringidle;
unsigned long ringstop;

bool isringing() {
  if (analogRead(A1) >40) {
    return true;
  } else {
    return false;
  }
}

void loop() {
  Serial.println( ringstop - ringstart );
  Serial.println(analogRead(A1));
  ringidle = millis();
  while (isringing()) {
    ringstart = ringidle;
    ringstop = millis();
  }
  Serial.println(ringstart);
  Serial.println(ringstop);
  Serial.println(ringstop - ringstart);
  if ( ringstop - ringstart >= 50 ) { \\Don't sense shorter button press less than 50ms
    while (ringstart == ringidle) {
      while (ringstop + (ringstop - ringidle) > millis()) { \\Keep relay opening the dor for the duration of ring button pressed
        digitalWrite(4, HIGH);
        Serial.println(ringstart);
        Serial.println(ringstop);
      }
      ringstop = -1;
      ringstart = -1;
    }
  }
  else {
    digitalWrite(4, LOW);
    ringstart = -1;
    ringstop = -1;
  }
}

Well the working code uses pin A0 and the non-working one uses pin A1. And the non-working code might work better if it actually compiled. Using the correct characters for comments would help there I think.

Doesn't the output from all those Serial.prints provide some useful debugging information? I confess I can't work out what you're trying to achieve with all those ringidle/start/stop variables and millis().

Steve

Hi, thanks for reading.

I have edited A(0) to A(1) for future refference.

I will try to explain.

Please note that both setups work fine when I do "the test", I lift up the interphone phone handle when I put it down both solutions work as expected. They open the door.

I have commented the "math" behind millis().

Basically I just calculate how long did I ring, than keep the door opened same duration as I rang.

If you can put beside the fact that the first code will work "better" my goal is to actually learn about C and Arduino, so this project will evolve as I learn hopefully.

So the issue is both solutions do work when I test from apartment with lift interphone phone from the case and then the speaker gets energized that is the moment voltage is read. When I put down the phone I measure duration of speaker being energized and turno on the relay for that duration.

Problem is that second solution does not work when I actually ring the interphone from downstairs.

So I guesed the issue is in the code somewhere but the fact that it is working from the apartment puzzles me.

I have recorded a video measuring the voltage when I ring from downstairs and it is the same as when I test from apartment.

Maybe I missed the forum group but I was not sure if it is sensing issue along with software part.

I'm not sure I understand. The code can't see where the voltage on the analog pin is coming from so it can't be doing anything different based on where the input comes from.

The only way the results can be different is if the input on the analog pin is doing something different. Which to me means it is effectively a hardware problem. Lifting the interphone and calling it from downstairs seem not to do exactly the same thing and the code doesn't cope with whatever that difference is.

Steve

Great. So you think the "logic" of the code is fine? I will then degub hardware wise. Maybe I will find another pin which has HIGH LOW values in the interphone circuit.

Thank you

Quick edit...

But then again how come the first code is working just fine? = )

That is what puzzling me. So I thought maybe tha way second code is written has some "hidden" thing that only experienced embedded developer can notice.

The big difference between those codes is that the first just detects a signal arriving on A1 and then uses fixed timing with delay() but the second seems to be trying to detect both the starting and stopping of the signal on A1.

I'd guess that's where the problem lies but I don't really have any clear idea of exactly what signal is connected to A1 and how it might be behaving differently in your two scenarios.

Steve

Yes I understand. Basically nothing is wrong but something is wrong = ).

I guessed there is not much that someone could helpout with this naving in mind I am not able to share entire setup because don't know how to share interphone parts and signal.

I will see what I can do different. Thank you anyhow.

Are you sure the ring signal is NOT a pulsating signal instead of steady DC?

I have posted one thread before this one. Now it seems like this is duplicate thread.
But only after few hours reading today.

I do have a pulsating signal. This is my last post in another thread. I will continue here because it is code issue.

After few hours of reading this morning, I also think that I have dug up the reason why i need to repair the code.

Signal is AC, the first code runs fast enough to detect positive side more than once in a millisecond.
And the doorlock is opened.

The second code detects voltage positive also and then in the next milli() it detects the end of ringing. The problem is in my ringing part of the code. I will all the same use "IF" = ).

I have posted another thread about counting frequency. But that is too far and advanced. This should work once I fix it. Will postback the final solution.

Now I am figuring out to accomplish this case:

As long as there is positive side measured on analogRead(A1) at least once in every 5 milisec I will assume that the ring is ringing.

As I see it I need to "emulate" analogRead(A1) return true even if it is not true in few millis() difference.

I know this is not a way to go, but this is my 5th day of coding after high school. So I reckon this must be doable code wise.

Here is what I have at the moment. I am stuck.

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

unsigned long ringstart = 0;
unsigned long ringidle;
unsigned long ringstop = 0;
int pass = 0;
int count;

bool isringing() {
  if ( analogRead(A1) > 10) {
    return true;
    count++;
  }
  else if ( count > 0 and ( analogRead(A1) == 0  and millis() - ringidle < 1)) {
    return true;
    count = 0;
  }
  else {
    return false;
  }
}

void loop() {

  if ( ! isringing() ) {
    Serial.println("IDLING");
    ringidle = millis();
  } else {
    Serial.println( "RINGING" );
    ringstart = ringidle;
  }
}

In your latest code:

    return true;
    count++;

You perhaps haven't realised that "return" does what it sounds like, it immediately exits from the function to the calling function. So it needs to be the last instruction, any code after return (like your count++ or count = 0) are never executed. Switch those lines round and see if it works better.

I think I would just have built a simple envelope follower/detector circuit rather than trying to emulate it in software but it's interesting to see the effort.

Steve

Yes, in a mild "panic" and excitement I posted what I had at the moment without any logical order of the code.

I will first completely understand this topic https://forum.arduino.cc/index.php?topic=503368.0. A beginners guide by UKHeliBob.

I beleive that this is the way I want to go to achieve "software emulation" for ringing state as long as POSITIVE pulses are present.

I guess I will need to have "backoff" time where arduino will know that the ringing is actually really stopped.