AVR. Training course

AVR. Training course

19.09.2023

In this short essay with photographs, I will show the general public how to treat a fairly common “sore” of digital electronic watches - inaccuracy. The clock can lag or rush, and most often we do not pay attention to small errors, but when the clock is behind by 5 (five) minutes a day, it begins to irritate.
Ready? Go!

Intro

I bought this watch in order to feel nostalgic for the old Soviet times, when the sun was greener and the grass was brighter... or vice versa?.. it doesn’t matter! The main thing is that there was no joy - the clock was disgustingly behind. More than 5 minutes a day. I need to heal, I thought.



Looking ahead, I would like to note that I did not open a dispute; one hundred rubles is not the same money. The problem is not with the seller who sent a low-quality product. The problem is in a product that the seller cannot check in any way - surely a Chinese man/woman will not sit and measure the accuracy of the move?

To treat the clock we need:

Necessarily
+ soldering iron. preferably not very powerful, 25-40 watts is enough. 60 will already be too much.
+ replacement quartz resonator. Sold either in China or in any radio store. It is inexpensive and is called “watch quartz.”
+ thin Phillips screwdriver or thin flat head screwdriver. cross is preferable.

Preferably
+ tweezers with sharp jaws - pick up the screws (yes, the body is plastic, the frame is also plastic. There are screws everywhere)
+ good lighting and a stationary magnifying glass or jeweler/watchmaker glasses to clearly see Little Red Riding Hood's watch.

We disassemble the watch

Unscrew the four screws holding the back cover. Carefully remove the cover and remove the piezoelectric resonator (tweeter). We do not paw the squeaker with our fingers; we hold it by the side edges and the metal base.


We note that the watch does not have a protective gasket, therefore water and sweat will get inside the watch. We understand that the Chinese save on everything for the sake of cheapness, which means that the glass is most likely sitting on double-sided tape and the buttons do not have rubber seals. This means that the watch will need to be removed in bad weather and during physical work.

We take the watch out of the case.


We put the case, back cover, back cover screws and tweeter aside.

We unscrew four screws - three hold the 2016 lithium battery, one holds the spring tab for sending a signal to the tweeter.


Let's put this all aside. We are considering the fee. You can't see any more screws, which means that's good.

Using tweezers, carefully remove the board from the plastic holder.


Inside the clip we see a conductive rubber band that transmits a signal to the LCD and the LCD indicator itself.
We don’t touch the elastic with our fingers, because it doesn’t matter. If a speck or dirt gets in, some segment on the indicator falls off and you have to take it apart again... what the hell...
In the blue heat shrink there is a coil that produces sound. There is no need to touch it either. It’s easy to damage, the wiring there is thinner than a hair.
But the metal cylinder on the legs is our quartz resonator, which needs to be changed.

To replace the quartz, I decided to use donor quartz from the old motherboard, which died ten years ago and I am slowly taking it apart into small components.


The quartz here is slightly larger than in watches.
Here, for comparison, is already soldered quartz from the motherboard and a clock board.


We apply quartz to the board. Fits. We put quartz in the cage, it also fits! Great! Let's change!

To replace, simply unsolder one quartz and solder in another.
There is no polarity, no features. The procedure is simple and does not require special qualifications.


Voila! quartz replaced. We align the quartz body so that it is just below the board and does not touch the battery.

Reassembly

We assemble the mechanism in the reverse order - we place the board on the holder, there are guide pins there. We put the battery on the board, minus pointing down.


Place the contact block on top of the battery. In this watch, it simultaneously holds the battery and is the contact group for the buttons. Fasten with three screws. Then a separate contact for the tweeter. We also screw it on.

We turn the block over and look - the clock should start. If this does not happen, it means either the battery is upside down or the quartz is not soldered in or it is not working or the board has been killed by static :)
Well, if everything works, carefully place the board in the watch case, center it so that the numbers are parallel to the edge, then install the beeper back, screw on the cover...

OK it's all over Now!
We have overcome a big problem)))

During the day the clock has not moved forward or backward, it runs smoothly and accurately. I'll watch it some more and then report back on the accuracy.

It must be said that the procedure for replacing quartz is the same for all quartz watches - digital, dial. But, we must remember that most Chinese quartz watches are assembled on plastic rivets, which are melted with “mushrooms”, i.e. in fact, once the watch is disassembled, it is very difficult to reassemble it.
Well, the size of the quartz also matters - if the quartz from the motherboard did not fit in size, then you would have to look for another, smaller one.

Outside the framework of this “Murzilka” there was a film that the Chinese did not remove from the LCD when they put it in the holder. I removed this film and the screen contrast increased slightly. The film is almost invisible, but it was on my watch.

UPD .
Over the past four days, since the quartz was replaced, the clock has moved forward by two seconds. 15 seconds per month.
For a cheap watch and free quartz, I think the result is satisfactory. Personally, it completely satisfies me)))
You can, of course, look for quartz watches for pennies at flea markets, pick up a bunch of quartz from there and experiment with precision... but we’ll leave that to perfectionists and die-hard freaks)))

The comments provide a recipe for finer-tuning the accuracy by soldering miniature ceramic capacitors. As an alternative to replacing quartz, it is quite viable and sensible. The main thing is that there is a place where to place these capacitors. Well, the presence of them...

And in general, friends, the main thing is not the review, the main thing is the comments)))
Thank you all for valuable ideas and various discussions)))

I'm planning to buy +16 Add to favorites I liked the review +91 +166

It would seem like a trivial matter to launch a watch quartz. What problems might there be? There is a microcontroller and its two legs, which are specifically designed for connecting quartz. There is a watch quartz. Soldering quartz is a matter of two seconds. Another minute is needed to add a couple of lines of timer initialization to the program. That seems to be all. BUT, after running this damn watch quartz for three days, I realized that the issue is not as simple as I thought.

And the background was like this. A friend asked me to make him a simple watch, without frills, with 7-segment indicators. No big deal. The microcontroller was taken ATmega48 (can work with clock quartz), a program was quickly written, and the signet was etched. After assembling the watch and debugging the program (dynamic display, buttons, etc.), it was time for the watch quartz. Before this watch, I had already used the watch quartz a couple of times in my projects and there were no signs of trouble :), but the unexpected happened - the watch quartz flatly refused to start. At all!
In an attempt to figure out what was preventing my watch quartz from working, I first turned to the datasheet for the microcontroller (ATmega48). There was very little information on the asynchronous mode and connecting the timer. Then I started looking for a solution to the problem on the forums. Here there was a variety of solutions and advice, including ritual dances with tambourines, which also didn’t really help me. I had to figure out what was what through trial and error (not to be confused with the “poke method”!). As a result of heroic efforts, stepping on every rake possible and killing three days, practical experience was born in connecting a watch quartz, which I will share here.

So, what rake awaits us when launching watch quartz?

1 Circuit design.
1.1 Capacitors.
The datasheet for the microcontroller mentions at some length that capacitors must be connected to the clock quartz, but it is generally difficult to find out about their capacitance. The clock quartz will most likely work without capacitors, but it is better to install them; this will improve frequency stability and help the quartz start up faster.
The capacitance of the capacitors should be in the range of 12-22 pF.

1.2 Layout of tracks for quartz.
Here the datasheet and apnots give us clear instructions. The paths from the microcontroller legs to the quartz should be of a minimum length, the ground path for the capacitors should be separate, that is, no extraneous currents should flow through it (especially for high-current and high-frequency circuits).

1.3 Watch quartz case.
Be sure to solder the iron case of the watch quartz to the ground (to the one to which the capacitors are soldered). An ungrounded case will act as an antenna, introducing distortions into the operation of the quartz, impairing the accuracy of your watch.

1.4 Dirt on the board.
Watch quartz is a rather delicate thing and a resistance of a couple of megaohms between the legs is quite enough to stop it. As practice has shown, liquid flux, if poorly washed off, provides sufficient resistance so that quartz does not work. After soldering, wash the board thoroughly. Very often, fluxes contain acid, which gives conductivity between the legs. To neutralize the acid, wash the board with a weak solution of baking soda and wash thoroughly with clean water.

2 Programming.
2.1 Initializing the asynchronous timer mode.

In order for the timer to work from a clock quartz, it (the timer) must be switched to asynchronous mode. To switch the timer (for almost all microcontrollers this is timer 2) to this mode, you need to write 1 to the AS2 bit. But not everything is so simple, you need to follow a certain launch algorithm. According to the datasheet, the procedure for enabling asynchronous mode for timer 2 is as follows:
1. Disable interrupts from timer/counter 2 - OCIE2x, TOIE2;
2. Switch it to asynchronous mode 1 -> AS2;
3. Write new values ​​to the TCNT2, OCR2x and TCCR2x registers;
4. Wait until the TCN2UB, OCR2xUB and TCR2xUB flags are reset;
5. Reset timer/counter 2 interrupt flags;
6. Enable interrupts (if required).

Be sure to follow this sequence. Here is a listing of the correct initialization of the asynchronous mode of timer2.

/* disable interrupts */ cli() ; /* 1. Disable Timer/Counter2 interrupts by resetting OCIE2x and TOIE2. */ TIMSK2 &= ~((1<< OCIE2A) | (1 << OCIE2B) | (1 << TOIE2) ) ; /* 2. Set Timer/Counter2 to asynchronous mode by setting AS2. */ ASSR = (1<< AS2) ; /* Give a little time for the generator to stabilize (can be omitted). */ _delay_ms(1000) ; /* 3. Write new values ​​TCNT2, OCR2x, and TCCR2B. */ TCNT2 = 0 ; /* set the limiter = 128 32.768 kHz / 128 / 256 = overflow once per second. */ TCCR2B |= (1<< CS22) | (1 << CS20) ; /* 4. To be sure that the clock has started working, wait until the bits are cleared: TCN2UB, OCR2AUB, OCR2BUB, TCR2AUB and TCR2BUB. */ while (ASSR & 0x1F ) ; /* 5. Reset the Timer/Counter2 interrupt flags. */ TIFR2 |= ((1<< OCF2A) | (1 << OCF2B) | (1 << TOV2) ) ; /* 6. Enable timer 2 overflow interrupt */ TIMSK2 |= (1<< TOIE2) ; /* enable interrupts */ sei() ;

/* disable interrupts */ cli(); /* 1. Disable Timer/Counter2 interrupts by resetting OCIE2x and TOIE2. */ TIMSK2 &= ~((1<

2.2 Timer limit 2.
In order for timer 2 overflow interrupts to occur once per second, the value of the limiter must be 128. (128 limiter * 256 overflow = 32768 quartz frequency).

2.3 Clock operation in PowerSave sleep mode.
It is very tempting to put the microcontroller into sleep mode in the pauses between second interruptions, in which case the microcontroller current will drop to 6-7 µA. For such a case, there is a PowerSave low-consumption mode, in which timer 2 continues to operate from the clock quartz and wakes up the microcontroller with an interrupt. The algorithm for this operating mode is simple: after exiting sleep mode by a timer interrupt, in the interrupt processing procedure we “tick” the clock, exit the interrupt and again give the command to sleep (SLEEP). There is a very important nuance here. Again, look at the datasheet for the microcontroller in the section on low consumption modes and asynchronous mode operation. In order for the timer to begin functioning normally after waking up and to be able to wake the microcontroller from sleep at the next interruption, you need to wait a certain time before the sleep command. In order to make sure that the generator is working normally, you need to write to any timer register, one that will not disrupt the clock (for example, in OCR2x) and wait for the readiness flags of this register to be reset (OCR2xUB). After the flag has been reset, you can safely put the microcontroller into sleep mode.

/* Exit point for timer2 overflow interrupt */ /* Write any value to OCR2A. */ OCR2A = 0; /* Wait until OCR2AUB is reset. */ while(ASSR & (1<

3 Miscellaneous.
3.1 Do not use cheap Chinese quartz(especially those soldered from old broken penny watches). Even if they work, they will have no accuracy.

3.2 And finally, have several different quartzes on hand, perhaps your quartz does not start due to the fact that it is sleeping. Try replacing it.

This, it seems, is all the rake that I trampled on while launching the watch quartz. Or is there anything else to add?


(Visited 9,748 times, 1 visits today)

Sometimes it is useful to have a clock in the system that counts time in seconds, and even with high accuracy. Often, special RTC (Real Time Clock) microcircuits like . It’s just that this is an additional case, and sometimes it costs as much as the MK itself, although you can do without it. Moreover, many MKs have a built-in RTC unit. It’s true that AVR doesn’t have it, but it does have an asynchronous timer that serves as a semi-finished product for making a watch.

First of all, we need a clock quartz at 32768 Hertz.

Why is quartz exactly 32768Hz and why is it called a sentry? Yes, everything is very simple - 32768 is a power of two. Two to the fifteenth power. Therefore, a fifteen-bit counter ticking at a frequency of 32768 Hz will overflow once per second. This makes it possible to build a clock using ordinary logical flow without any problems. And in the AVR microcontroller, you can organize a clock with seconds almost without using the brain, using peripheral reflexes.

Asynchronous Timer Mode
Remember how timers work? The clock frequency from the main clock generator (RC external or internal, external quartz or external oscillator) goes to the prescalers, and from the output of the prescalers it already clicks the values ​​of the TCNT register. Or the input signal comes from the counting input Tn and also clicks the TCNT register

To do this, a quartz resonator is hung on the pins TOSC2 and TOSC1. Low frequency, usually an hour quartz at 32768Hz. It is mounted to the right of the controller and connected with jumpers. Moreover, the processor clock frequency must be at least four times higher. We have a clock from the internal oscillator of 8 MHz, so this condition does not bother us at all :)

And you don’t need to calculate the number of cycles of the main quartz, and if it doesn’t exist, then bother with the floating frequency of the built-in RC oscillator. Watch quartz has a much more compact size than regular quartz, and is cheaper.


Also important is the fact that the asynchronous timer can tick on its own, from the clock quartz, because it does not need the processor clock frequency, which means that the clocking of the controller core (the hardest thing it has) can be turned off by hibernating the processor, significantly reducing energy consumption and waking up only when the timer overflows (1-2 times per second) to record new time readings.

Configuration
To turn it on, you just need to set the AS2 bit of the ASSR register - and that’s it, the timer operates in asynchronous mode. But there is one feature here that cost me a lot of headaches at one time. The fact is that when operating from your own quartz, all internal timer registers begin to synchronize using their own quartz. But it is slow and the main program can change an already entered value much faster than it can be processed by the timer.

That is, for example, you preset the value TCNT2, the timer on your 32 kHz thresher hasn’t even had time to chew it yet, but your algorithm has already run through and written something there again - as a result, garbage will probably end up in TCNT2. To prevent this from happening, the recording is buffered. Those. you think that you wrote the data to TCNT2, but in fact it ends up in the temporary register and will only get to the counting register after three clock cycles of the slow generator.

The OCR2 comparison registers and the TCCR2 configuration register are also buffered

How can I find out whether the data has already been entered into the timer or is hanging in intermediate cells? Yes, it’s very simple - using the flags in the ASSR register. These are the TCN2UB, OCR2UB and TCR2UB bits - each is responsible for its own register. When we, for example, write a value to TCNT2, TCNUB becomes 1, and as soon as our number from the intermediate register moves into the real counting register TCNT2 and begins to tick, this flag is automatically reset.

Thus, in asynchronous mode, when writing to the TCNT2, OCR2 and TCCR2 registers, you first need to check the TCN2UB, OCR2UB and TCR2UB flags and write only if they are equal to zero. Otherwise the result may be unpredictable.

Yes, another important point - when switching between synchronous and asynchronous modes, the value in the TCNT counter register may be lost. So to be safe, we switch like this:

  • Disable interrupts from this timer
  • Switch to the desired mode (synchronous or asynchronous)
  • We set up the timer again as needed. Those. set the TCNT2 preset if necessary, re-configure TCCR2
  • If we switch to asynchronous mode, then we wait until all the TCN2UB, OCR2UB and TCR2UB flags are reset. Those. the settings have been applied and are ready to go.
  • Resetting the timer/counter interrupt flags. Because with all these perturbations they can accidentally settle
  • Enable interrupts from this timer

Failure to follow this sequence leads to unpredictable and difficult to detect glitches.

Sleep modes and asynchronous timer
Because an asynchronous timer is often used in various saving modes, then one feature arises that creates a whole field of rake.

The bottom line is that a timer powered by slow quartz cannot keep up with the main processor, and there are a lot of dependencies on the peripherals - the same interrupts, for example. And when the processor sleeps, these dependencies cannot be implemented, resulting in glitches such as broken interrupts or corrupted values ​​in registers. So the logic for working with an asynchronous timer and sleep mode should be built in such a way that between waking up and putting it into hibernation, the asynchronous timer has time to work out several of its clock cycles and complete all its tasks.

Examples:
The controller uses power saving and core shutdown mode, and wakes up by interrupts from an asynchronous timer. Here we must take into account the fact that if we change the values ​​of the TCNT2, OCR2 and TCCR2 registers, then hibernation should be done ONLY after the TCN2UB, OCR2UB and TCR2UB flags fall. Otherwise, the result will be such a mess - the asynchronous timer has not yet had time to pick up data from the intermediate registers (it is slow, hundreds of times slower than the core), and the core has already been cut off. And it would be nice if the new configuration wasn’t applied, this is nonsense.

What’s worse is that while the TCNT or OCR registers are being modified, the operation of the comparison unit is blocked, which means that if the core falls asleep earlier, the comparison unit will never start - there will be no one to turn it on. And we will lose the interruption in comparison. The risk is that we will miss the event and lose them until the next awakening from hibernation.
What if the controller is woken up by a comparison interrupt? Then he will fall asleep completely. Oops!
So catch this glitch later.

So before going into power saving modes, you must definitely let the asynchronous timer chew on the entered values ​​(if they were entered) and wait for the flags to reset.

Another joke with the asynchronous mode and energy saving is that the interrupt subsystem, when exiting hibernation, starts in 1 clock cycle of the slow generator. So even if we haven’t changed anything, we can’t go back into hibernation - we won’t wake up, because... interrupts will not have time to run.

So coming out of hibernation and going to sleep when interrupted by an asynchronous timer should look like this:

  • Woke up
  • They did something necessary
  • Fell asleep

And the duration of the operation between Woke up and Falling asleep SHOULD NOT BE LESS than one tick of the asynchronous timer. Otherwise, suspended animation will be eternal. You can set the delay, or you can do it as the datasheet advises:

  • Woke up
  • They did something necessary
  • Just for fun, we wrote something in any of the buffered registers. For example, in TCNT there was 1, and we recorded 1 again. Nothing has changed, but a recording occurred, the TCN2UB flag was raised, which is guaranteed to last three cycles of the slow generator.
  • Wait until the flag falls
  • We fell asleep.

It is also not recommended to immediately read the TCNT values ​​when exiting hibernation - it can be considered a mess. It's better to wait one tick of the asynchronous timer. Or make a joke with writing to the register and waiting for the flag to fall, as was written above.

Well, the last, but important, point - after applying power, or coming out of deep hibernation, with the shutdown of not only the core, but in general the entire periphery, it is strongly recommended to use a slow generator no earlier than after 1 second(not a millisecond, but a whole second!). Otherwise, the generator may still be unstable and there will be more mess and garbage in the registers.

And, at the end of the article, a small example. Running an asynchronous timer on Atmega16 (How the board is used by the polygon)

The project is standard, based on a dispatcher, the only difference is that the dispatcher has been transferred to timer0 to free up timer2.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int main(void) (InitAll(); // Initialize the peripheral InitRTOS() ; // Initialize the kernel RunRTOS(); // Start the kernel. UDR = "R" ; // Start marker, for debugging SetTimerTask(InitASS_Timer, 1000 ) ; // Since the timer in asynchronous mode // starts slowly, we do // Delay to start initializing the timer. while(1) // Main dispatcher loop( wdt_reset() ; // Reset dog timer TaskManager() ; // Call the dispatcher) return 0 ; )

int main(void) ( InitAll(); // Initialize the peripheral InitRTOS(); // Initialize the kernel RunRTOS(); // Start the kernel. UDR = "R"; // Start marker, for debugging SetTimerTask(InitASS_Timer,1000) ; // Since the timer in asynchronous mode // starts slowly, we make // a delay to start initializing the timer. while(1) // Main loop of the dispatcher ( wdt_reset(); // Reset the dog timer TaskManager(); // Call dispatcher ) return 0; )

The procedure for initializing the timer in asynchronous mode is made in the form of a finite state machine. When it first starts, it sets the asynchronous mode bit and makes preparations, then it starts itself again, through the dispatcher, to give something else the opportunity to slip through the queue without blocking the system while waiting.

On subsequent inputs, the ready flag bits of the timer registers are checked. If they are all zeros, then just in case we reset the timer interrupt flags to avoid glitches and false positives, and then enable the interrupt we need. And we go out.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 void InitASS_Timer(void ) ( if (ASSR & (1<< AS2) ) //If this is the second input then( if (ASSR & (1<< TCN2UB | 1 << OCR2UB | TCR2UB) ) // check if there is at least one flag bit( SetTask(InitASS_Timer) ; // If there is, then we send it to a repeat waiting cycle) else // If everything is clear, then you can run interrupts(TIFR |= 1<< OCF2 | 1 << TOV2; // Reset interrupt flags, just in case. TIMSK |= 1<< TOIE2; // Enable overflow interrupt return ; ) ) TIMSK &= ~(1<< OCIE2 | 1 << TOIE2) ; // Disable timer 2 interrupts ASSR = 1<< AS2; // Enable asynchronous mode TCNT2 = 0 ; TCCR2 = 5<< CS20; // A prescaler of 128 by 32768 will give 256 ticks per second // Which will give 1 overflow interrupt per second. SetTask(InitASS_Timer) ; // Run it through the dispatcher to log in again. }

void InitASS_Timer(void) ( if(ASSR & (1<

ISR(TIMER2_OVF_vect) // Timer 2 overflow interrupt ( UDR = i; i++; )

It was possible to make variables containing hours:minutes:seconds and click those variables with all their hour/minute overflow logic, but I was too lazy. And so everything is clear.

© 2023 hecc.ru - Computer technology news