Serial monitor print only <He>

Hi
Why this program is printing only He in serial monitor ? ?


void setup() {
   Serial.begin(115200);

  pinMode(9, OUTPUT); //output A
  pinMode(10, OUTPUT); //output B

  //Enable pin change interrupts on pins 9 and 10 PB 2 and 3
  PCICR |= (1 << PCIE0); //enable group interrupts on PORTB PCINT[7:0]
  PCMSK0 |= (1 << PCINT2); //enable interrupt pin 10
  PCMSK0 |= (1 << PCINT1); //enable interrupt pin 9

  TCCR1A = 0; //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;
  GTCCR |= 1 << PSRASY; //reset prescaler

  TCCR1B |=  _BV(CS11); // prescaler 8
  //TCCR1B |= _BV(CS10); //no prescaler
  ICR1 = 199;//
  OCR1A = ICR1 - 1; //two different pulse widths almost 100% duty cycle
  OCR1B = OCR1A / 2; //offset by half period

  TCCR1B |= _BV(WGM13) | _BV(WGM12); //CTC mode with ICR1
  TCCR1A = _BV(COM1A0) | _BV(COM1B0); //Toggle OC1A/OC1B on compare match

}

void loop() {

  Serial.println("Hello, world!");
}

Try adding Serial.flush(); after the Serial.println();

See Serial.flush() - Arduino Reference

What is the program supposed to do?

Where is the pin change interrupt service routine?

Because you enabled an interrupt without providing an interrupt handler. The default handler resets the processor.

Thanks to all, johnwasser suggestion is working.

Now I am trying to change a frequency, it is working from 5 to 10 kHz, I need up to 20 kHz


unsigned long amp = 0;
void setup() {

  Serial.begin(115200);
  pinMode(A3, INPUT_PULLUP);
  pinMode(A4, INPUT_PULLUP);
  pinMode(9, OUTPUT); //output A
  pinMode(10, OUTPUT); //output B

  //Enable pin change interrupts on pins 9 and 10 PB 2 and 3
  PCMSK0 |= (1 << PCINT2); //enable interrupt pin 10
  PCMSK0 |= (1 << PCINT1); //enable interrupt pin 9

  TCCR1A = 0; //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;
  GTCCR |= 1 << PSRASY; //reset prescaler

  TCCR1B |=  _BV(CS11); // prescaler 8
  //TCCR1B |= _BV(CS10); //no prescaler
  ICR1 = 200;//
  // ICR1 = amp;//
  OCR1A = ICR1 - 1; //two different pulse widths almost 100% duty cycle
  OCR1B = OCR1A / 2; //offset by half period

  TCCR1B |= _BV(WGM13) | _BV(WGM12); //CTC mode with ICR1
  TCCR1A = _BV(COM1A0) | _BV(COM1B0); //Toggle OC1A/OC1B on compare match
 
  EEPROM.get(500, amp);
}

void loop() {

  // for (int amp = 0; amp <= 255; amp++)
  //for (int amp = 100; amp <= 255; amp++)// scanning
  // for (int amp = 99; amp <= 200;)// 99 = 10 kHz, 200 = 5 kHz

  //{
  ////////////////
  if (digitalRead(A3) == 0) {
    amp++;

    EEPROM.write(500, amp);
  }
  if (digitalRead(A4) == 0) {
    amp--;

    EEPROM.write(500, amp);
  }
  ICR1 = amp; //

  Serial.print("amp=");
  Serial.println(amp);
  delay(100);

  // }
}

I assume your running a 328? 16mhz?

that code got you working in the 5-10khz? surprising

prescale 8 should be in the 1-2 mhz range

(timer speed (Hz)) = (Arduino clock speed (16MHz)) / prescaler

try prescaller 64, the top end puts you at 25khz (16mhz/64).

TCCR1B=0b00011011;

should get you into the right range, I didn't look at the rest of your code too carefully, as you said it was working.

That's the clock speed. You also have to divide by the number of counts per cycles (ICR1 + 1?).

16 MHz / 8 = 2 MHz / 201 = 9950.248 Hz

And, since it is WGM 12 (CTC) the output toggles once per count so the resulting frequency is half:

4975.124 Hz

For higher frequencies, use lower values for TOP (ICR1) or use a lower prescale.

Note: Timer1 is a 16-bit timer so ICR1 can go up to 65535. You can use a prescale of 1 and get frequencies from 122 Hz to 4 MHz.

I made prescaler 1

   TCCR1B = (1<<WGM13) + (1<<WGM12) + (1<<CS10); // prescaler = 1 (none)

It is go up to 80 kHz = ok, but EEPROM is not saving the values.

#include <EEPROM.h> 
unsigned long amp = 0;
void setup() {

  Serial.begin(115200);
  pinMode(A3, INPUT_PULLUP);
  pinMode(A4, INPUT_PULLUP);
  pinMode(9, OUTPUT); //output A
  pinMode(10, OUTPUT); //output B

  //Enable pin change interrupts on pins 9 and 10 PB 2 and 3
  PCMSK0 |= (1 << PCINT2); //enable interrupt pin 10
  PCMSK0 |= (1 << PCINT1); //enable interrupt pin 9

  TCCR1A = 0; //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;
  GTCCR |= 1 << PSRASY; //reset prescaler
  
  //+++++++++++++++++++++++++++++++++++++++++
    TCCR1B = (1<<WGM13) + (1<<WGM12) + (1<<CS10); // prescaler = 1 (none)
 //+++++++++++++++++++++++++++++++++++++++++++++
 
  ICR1 = 200;//
  // ICR1 = amp;//
  OCR1A = ICR1 - 1; //two different pulse widths almost 100% duty cycle
  OCR1B = OCR1A / 2; //offset by half period

  TCCR1B |= _BV(WGM13) | _BV(WGM12); //CTC mode with ICR1
  TCCR1A = _BV(COM1A0) | _BV(COM1B0); //Toggle OC1A/OC1B on compare match
 
 EEPROM.get(5, amp);
}

void loop() {

  // for (int amp = 0; amp <= 255; amp++)
  //for (int amp = 100; amp <= 255; amp++)// scanning
  // for (int amp = 99; amp <= 200;)// 99 = 10 kHz, 200 = 5 kHz

  //{
  ////////////////
  if (digitalRead(A3) == 0) {
    amp++;

   EEPROM.write(5, amp);
  }
  if (digitalRead(A4) == 0) {
    amp--;

  EEPROM.write(5, amp);
  }
  ICR1 = amp; //

  Serial.print("amp=");
  Serial.println(amp);
  //delay(100);

  // }
}

Still no ISR, so the program is not running at all.

If it did run, it would burn up the EEPROM memory cell in short order.

I double check it is working but amp must be greater than 100, you can remove EEPROM for your safety . The strange thing is happening, when I when I divide by amp bay any number , numbers on serial monitor are not changing, without dividing is ok.
//Serial.println(amp/3700); = not good
Serial.println(amp) = ok

updated with ISR, generator is working, EEPROM not

#include <EEPROM.h>
unsigned long amp = 0;
void setup() {

  Serial.begin(115200);
  pinMode(A3, INPUT_PULLUP);
  pinMode(A4, INPUT_PULLUP);
  pinMode(9, OUTPUT); //output A
  pinMode(10, OUTPUT); //output B

  //Enable pin change interrupts on pins 9 and 10 PB 2 and 3
  PCMSK0 |= (1 << PCINT2); //enable interrupt pin 10
  PCMSK0 |= (1 << PCINT1); //enable interrupt pin 9

  TCCR1A = 0; //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;
  GTCCR |= 1 << PSRASY; //reset prescaler

  //+++++++++++++++++++++++++++++++++++++++++
  TCCR1B = (1 << WGM13) + (1 << WGM12) + (1 << CS10); // prescaler = 1 (none)
  //+++++++++++++++++++++++++++++++++++++++++++++

  //ICR1 = 200;//
  //ICR1 = amp;//
  OCR1A = ICR1 - 1; //two different pulse widths almost 100% duty cycle
  OCR1B = OCR1A / 2; //offset by half period

  TCCR1B |= _BV(WGM13) | _BV(WGM12); //CTC mode with ICR1
  TCCR1A = _BV(COM1A0) | _BV(COM1B0); //Toggle OC1A/OC1B on compare match

  // EEPROM.get(0, amp);
}

void loop() {
  ICR1 = amp;
  if (digitalRead(A3) == 0) {
    amp++;

    //EEPROM.write(0, amp);
  }
  if (digitalRead(A4) == 0) {
    amp--;
    //EEPROM.write(0, amp);
  }


  Serial.print("amp Hz = ");
  Serial.println(amp);
  // Serial.println(amp/10);

}

what exactly do you mean "its working"? just that the program is running? or are you measuring the output on a scope?

You're not actually using any of the timer stuff you setup. If your timer is running, its not doing anything. You need an attachinterrupt() call & a function to be called when the ISR hits. if I understand how you set it up(CTC), that vector should be TIMER1_COMPB_vect. Then write the function to do what you want to happen when it hits. If its just a pwm, then that function is just a pin toggle(preferably by direct port manipulation). Keep the ISR short, definitely no serial prints from within.

why are you writing to eeprom so frequently? That seems like a terrible idea.

when messing with registrations, its best to use cli(); & sei() to stop & start interrupts. just add the cli before you start & the sei when your done. Not doing this can cause generally inconsistent things to happen.

interrupts() & noInterrupts() does that same thing, as i recall they are just macros for cli & sei

edit: here is a good primer on interrupts, as well as a table with all the ISR vectors incase the one I stated is incorrect: all about interrupts

By pressing the buttons I am changing the frequency of the generator

Yes

Only when I am pressing the button, I need to adjust the frequency and have it the same when power is ON/OFF

ok tom, that gives me a much better idea whats going on.

as a test, try adding cli() & sei() to your epprom writes. Since you say it worked at lower frequency, I suspect writing to epprom is taking longer then the time between interrupts, thus causing it to fail. just a theory, but easy to test:

cli();
EEPROM.write(0, amp);
sei();

note that you will loose a few interrupts in doing this, if thats critical to your application, you'll have to find a work around. at least you can confirm or rule out my theory.

Don't know how to use it, can you modify code from post # 12 ?

i thought I did in #15? I'd rather explain how it works thats just give you the code.

It looks like your epprom writes are commented out, assuming thats where where your writes were happening when it was working, you need to add cli(); or noInterrupts(); before the write line. This turns off all interrupts so you're not interrupted in the middle of a write (as I've speculated is happening) When your write is complete sei(); or interrupts(); Will resume interrupts so your program can continue

in summary: cli() the same as noInterrupts() --no arguments, just stops them
sei() is equivalent to interrupts() -no arguments, resumes interrupts.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.