1

I need a short beep for every minute of change. I wrote a separate function. The signal duration should be 50 ms, the rest of the time the emitter connected to the A1 contact should be silent.

A really working sketch is shown below:

uint32_t mysound; // Variable for storing time (duration of the sound signal)
uint32_t myTimer1;
uint32_t t; //Time that always increases
byte seconds; // Seconds
byte minutes; // Minutes
int k = 1;
void setup()
{
  DDRC = B00000010; // Set pin A1 as output
  //      76543210
  Serial.begin(9600);
  myTimer1 = millis();
}

void loop()
{
  t = (millis() - myTimer1) / 1000; // Time in seconds
  seconds = t % 60; // when 60 seconds are reached, it is reset to zero
  minutes = t / 60 % 60; // Counts the minutes and drops to zero when 60 minutes are reached
  Serial.println(seconds);
  if (seconds == 0 && k)
  {
    sound();
  }
  if (seconds > 0) k = 1;
}

void sound()
{
  mysound = millis();
  while (millis() - mysound < 50)
  {
    PORTC = B00000010; // We set high voltage on pin A1 for a time of 50 ms
  }
  k = 0;
  PORTC = B00000000;
}
5
  • doesn't work is a meaningless description of what you observed ... please describe what happens ... also, describe what tests you performed to make sure that the piezo emitter works
    – jsotola
    Feb 5, 2021 at 4:35
  • does the piezo make sound with pin HIGH?
    – Juraj
    Feb 5, 2021 at 5:55
  • Yes, if you just raise the pin to a high level, then the piezo emitter beeps
    – Антон
    Feb 5, 2021 at 7:02
  • All my attempts end with him either constantly beeping or constantly silent. I was unable to achieve a short-term peak
    – Антон
    Feb 5, 2021 at 7:03
  • 1
    I assume, you are using atmega328 or atmega2560 when using register PORTC instead of digitalWrite() for generic arduino board. Are you trying to avoid using TIM1 or TIM2? And so maybe there is a reason to avoid using delay() as well. So try this one single line code >>>> if ((millis() % 60000) < 50) PORTC |= 0x02; else PORTC &= ~0x02;
    – SimonVu14
    Feb 5, 2021 at 13:09

2 Answers 2

4

Your myTimer1 in t = (millis() - myTimer1) / 1000; is not set

3

In addition to Qareke's answer, you also have a problem with the mysound variable. You only set this timestamp to millis() inside your millis() if statement. mysound is global and thus will be implicitly initialized with zero. So, by the time, that the code reaches the if statement, the difference between millis() and mysound is most likely already too big, thus the timestamp gets never set.

Solution: You need to move 2 lines around in your code:

  • Move the mysound = millis(); statement up into the if (seconds == 0) statement.
  • Move the sound(); statement outside of the if statement directly into the void loop() function (for example directly after the if (seconds == 0) statement).

Now the sound() function will always be executed, but it will only do a sound, if the timestamp was set to millis() previously, and then only for 50ms. Now we only need to make sure, that the timestamp variable mysound will only be set once, when the seconds get zero. You could either introduce a new flag variable for that, or you could just use the timestamp itself and check, if more than 1s passed since the last time the timestamp was set. So you need to change

if (seconds == 0)

to

if (seconds == 0 && millis() - mysound > 1100)

I used 1100 (1.1s) here, to make sure, that there is no bad edge case happening. Since seconds will only get zero every minute, that shouldn't be a problem.

2
  • Sorry, but I did not understand how you can move a function call out of a condition. Then what remains within the condition? I fixed the program from above, in this form the squeak starts but never stops
    – Антон
    Feb 5, 2021 at 9:26
  • 1
    If you read my answer closely, you see, that I instructed you to move the mysound = millis(); statement inside that if statement. But you have put still inside the sound() function. Also you have chosen to use a flag variable (instead of the proposed millis() solution). So you haven't used my solution to the problem. Nonetheless, your current code works perfectly for me. I don't have a piezo at hand, but my logic analyser shows a 50ms long positive pulse every minute. If that doesn't work for you, probably there is something wrong with your wiring
    – chrisl
    Feb 5, 2021 at 10:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.