Hacking watch winder issue - integrating a programmable chip

Hello there.

I have a problem that I can't solve and would ask for your explanation and help. Thank you.

I am relatively new to the Arduino world, despite playing around with it for a few years now.
I have an automatic watch that needs to be rotated every day in order to keep it's power reserve. That is why a device that periodically rotates, or winds it, is needed (unless you want to do this every single day by hand using the crown). That is why I recently bought a device that is supposed to do this work for me, automatically. The device is called watch winder and in a nutshell it is a box with a DC motor inside with a holder for the wristwatch attached to the shaft of the motor (or the the shaft of the last reducing gear, since a a basic DC motor spins way too fast for a watch).

Since I made the mistake to go cheap and bought one of the least expensive watch winders, which turned out to be a mistake. This winder features a small PCB and a DPDT switch used as a polarity reverse switch (to make the motor switch it's direction of rotation, yes I know, they didn't use H-bridge but made this manually operated). The big problem comes when I read about the board inside the winder. It was programmed to make a total of over 2000 revolutions per day of the wristwatch. Now, this is way too much for a normal watch. Modern ones do not have a problem if you over wind them because they have a mechanism called safety clutch inside that prevents the spring form being overwound, but that clutch should not be engaged all the time because it might malfunction after some time (from what I have read about overwinding an automatic watch). A standard watch requires typically around 650-900 revolutions per day.
This is why I decided to to implement an IC with a simple code to control the motor (which by the way used to operate on 4V from the provided power supply but I changed that for 5V because of the chip). I made the code so that the total number of revolutions per day would be around 700.

I am providing the code down below:

int a = 3;
int x = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(a,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  while(x < 100){
  digitalWrite(a,HIGH);
  delay(56000);
  digitalWrite(a,LOW);
  delay(4000);
  x = x + 1;
  }
  x = 0;
  digitalWrite(a,LOW); //just to be sure that it won't rotate for 80400 seconds
  delay(80400000); // Rotation: 6000 seconds, Rest: 80400 seconds
}

The idea is that the ATtiny85 instructs the motor to rotate for 56 seconds, then to rest for 4 seconds and this cycle is repeated 100 times (so it takes 100 minutes to complete it).

Below I am providing the schematic (made on Fritzing, uploaded as a screenshot):


(battery pack used here but in reality it is a 5V charger adaptor for a phone with USB cable)

As you can see, the ATtiny85 does not directly control the motor (since it would most likely not be able to handle the current this motor required) but instead it turns on a NPN transistor (in my case I have used 2N2222A) that acts as a switch.

Everything sounds really sweet until I tell you that... it never comes to a stop. The program exceeds 100 minutes run time and seemingly rotates the motor forever (it could theoretically stop in many hours but I am impatient to wait tens of hours before it stops).

Now, the analysis.

At first, I thought that the code was somewhat wrong so I rewrote it (but this is irrelevant to you because the code I provided is the final prototype, even though the first one was basically the same but instead of while() loop I used for() loop). It was not the code.

Next thing I did I ran the code on the ATtiny85 but not with a transistor and a motor but with a LED and it worked seamlessly. So it definitely was not the code. I did the same thing with the NPN and there was no problem at all.

I was very baffled until I thought that maybe the motor is meddling with the performance of the chip by sending spikes of reverse voltage (or whatever inductors do when the power is cut off). That is why I added a small diode in reverse that in theory should "kill" these voltages. Alas, the problem still persisted.

Left with little to no options, I did something that could be helpful in determining the problem. I modified the code so that on every cycle initiation (aka every time the pin is driven HIGH), through a serial communication with Arduino Uno (which communicates with the serial monitor on my PC) the ATtiny85 would send the value of "x" (the control variable that increases in value). I noticed something really strange.

When I did this merely with a simple LED, the results were just as expected: 0 1 2 3 ... 97 98 99 and it stops there (I added spaces between the numbers here but in reality it was more like 0123456). Nothing suspicious here, BUT when I did the same "diagnostics" with the proper load, aka the motor and the transistor, the numbers where as follows: 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 9 10 12 12 13 0 1 2... I left it like this for like 4-5 hours and it had reset a few times it had reached the number 65 and had gone back to 0. As you can see, for some god-knows-why reason the chip decides to reset it's value every now and then. I don't know if the whole IC is resetting. I do not know if there are some interruptions or interferences or whatever. I simply don't know.

That is why I am writing here and I hope for your support and suggestions. Thank you very much for reading this annoyingly long post.

Unless your watch has a perpetual calendar that takes a long time to set, Google "why watch winders are bad" or something like that.

Then turn the watch winder into something useful or place it in the recycling bin.

Then you get an extra minute from time to time, to watch your watch, while you are setting it. That is why you paid the big bugs. :slight_smile:

As a first step I would not use delay - look at the „Blink without delay“ example. (Delay is handy if you need to stall the sketch for some millisecs for some execution to complete.)
A better way to wait a while is to store the start-time and check with every loop if the designated interval has passed. Thats what the „Blink without delay“ example does.
I am not familiar with the ATtiny but there might be some sort of watchdog function that balks at the long delays.