For a customer project I am retrofitting an old telephone and am using a nano inside the chassis to control the bell using a nano, a movement sensor and the phones speaker for input, and a relais as an output to power the bell.
I tested the system with an uno, it worked flawlessly. I also tested it using wokwi with a slightly modified code to compensate for differences with the inputs etc, the timings are the same though.
When I set up the final build using the nano with a 12v psu (movement sensor requires 12-36v so this was the sweet spot) the phone bell works flawlessly, only the cooldown at the end of the program seems to sometimes get swallowed up and the phone does not return to the idle state.
const int hoerer = 2; //Digital Pin 2 (hoerer = speaker)
const int melder = 3; //Digital Pin 3 (melder = movement sensor)
const int relais = 4; //Digital Pin 4
int hoererState = 0; //0 means contact is closed, 1 is open
int melderState = 1; //like hoererState
int bellState = 0; //is the bell currently ringing?
int klingelCounter = 0; //how often was the bell ringing?
int abgehoben = 0; //State-bit to only trigger relais once (not really necessary but i wanted it for security)
int cooldownTriggered = 0; //Starts the Counter for Cooldown
int klingelZeitAn = 2500; //Time the bell is ringinging in ms
int klingelZeitAus = 4000; //Time the bell is not ringing in ms
unsigned long cooldownZeit = 45000; //Time for which the phone shall not ring after hanging up
unsigned long lastBellTime = 0; //When did the bell ring for tha last time?
unsigned long lastCooldownTime = 0; //When was the last time the cooldown was started?
enum status{
IDLE, KLINGEL, ABGEH, COOLDOWN
};
int state = IDLE;
void idle(); //Idle-State
void klingel(); //Ringing-State
void abgeh(); //Phone was picked up state
void cooldown(); //Cooldown-state
void setup() {
pinMode(relais, OUTPUT);
digitalWrite(relais, HIGH); //first of all we don't want the phone to ring
pinMode(melder, INPUT_PULLUP);
pinMode(hoerer, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("System online");
}
void loop() {
melderState = digitalRead(melder);
hoererState = digitalRead(hoerer);
if(state == IDLE){
idle();
}
if(state == KLINGEL){
klingel();
}
if(state == ABGEH){
abgeh();
}
if(state == COOLDOWN){
cooldown();
}
if(hoererState == 1){ //Quasi-Interrupt when the speaker is picked up allowing us to change to picked up state no matter where we are in the program
if(abgehoben == 0){ //Causes these instructions to only be executed once
Serial.println("Picked up");
digitalWrite(relais, HIGH);
abgehoben = 1;
state = ABGEH;
}
}
delay(10);
}
void idle(){
if(melderState == 0){ //when movement-sensor is triggered we go to bell state
state = KLINGEL;
bellState = 0;
Serial.println("Going to ringing-state");
}
}
void klingel(){
unsigned long bellTime = millis();
if(bellState == 0 && ((bellTime - lastBellTime) > klingelZeitAus)){
bellState = 1;
digitalWrite(relais, LOW);
Serial.println("Bell on");
lastBellTime = bellTime;
}
if(bellState == 1 && ((bellTime - lastBellTime) > klingelZeitAn)){
bellState = 0;
digitalWrite(relais, HIGH);
Serial.println("Bell off");
klingelCounter++;
if(klingelCounter > 4){ //Bell-counter, when nobody picks up the phone we also go to cooldown
state = COOLDOWN;
cooldownTriggered = 0; //Start signal Cooldown
klingelCounter = 0;
Serial.println("reset klingelCounter");
}
lastBellTime = bellTime;
}
}
void abgeh(){ //
if(hoererState == 0){ //Only when the speaker is hung up we go to cooldown
state = COOLDOWN;
Serial.println("Hanged up");
abgehoben = 0; //so we can restart the whole process
cooldownTriggered = 0; //Start signal for cooldown
}
}
void cooldown(){
unsigned long cooldownTime = millis();
if(cooldownTriggered == 0){
lastCooldownTime = cooldownTime;
cooldownTriggered = 1;
klingelCounter = 0;
Serial.println("Starting Cooldown");
}
if((cooldownTime - lastCooldownTime) > cooldownZeit){
state = IDLE;
Serial.println("Cooldown finished, back to Start!\n");
lastCooldownTime = cooldownTime;
}
}
as i did further testing i noticed once, that the phone would ring constantly until it was picked up and afterwards did not go back to the idle state.
I am at a loss as i have never had this kind of behaviour during testing and it only came up once i was assembling the piece on site using the nano.
Thanks for any suggestions that can help resolve the issue.
EDIT:
Somebody passing by just triggered the phone and it would not stop ringing (not reacting to bell counter).. I have no explanation for this. Is it possible this arduino is simply DOA?