Pages: [1]   Go Down
Author Topic: My code needs Serial.begin to work but I do not need Serial support in my code  (Read 529 times)
0 Members and 1 Guest are viewing this topic.
Vilvoorde Belgium
Offline Offline
Newbie
*
Karma: 1
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The code here below works fine. It generates a pulse place modulation signal with 8 channels.

HOWEVER

If you comment out the Serial.begin(9600) … it does not generate the last (the 8th) channel. It in fact becomes unstable … an 8th channel comes up and moves from a much too small to a much too big pulse and after that you have a perfect 7 channel PPM signal…and after a very long time the 8th channel comes up again.
 
Anyone who has a hint?… because I’ve now tried many things for 7 hours and I am lacking inspiration.

Jan Huygh

PS:  I had the Serial.begin in my code for debugging

Code:
//Convenience macros
#define TC1_ConnectToPrescaler_8 TCCR1B &= ~((1<<CS12) | (1<<CS10)) ; TCCR1B |= (1<<CS11)
#define TC1_ClearOnCompareMatchWithOCR1A TCCR1A &= ~((1<<WGM11)|(1<<WGM10)); TCCR1B &= ~(1<<WGM13); TCCR1B |= (1<<WGM12)
#define TC1_EnableInterruptOnCompareMatchWithOCR1A TIMSK1 |= (1<<OCIE1A)
#define TC1_EnableInterruptOnCompareMatchWithOCR1B TIMSK1 |= (1<<OCIE1B)
#define TC1_DisableInterruptOnCompareMatchWith0CR1B TIMSK1 &= ~(1<<OCIE1B)

const byte PPM_Pin = 12;
volatile byte PPM_Progress = 0;
volatile word CHX_Pulse[7];

void setup () {
  Serial.begin(9600);
  pinMode(PPM_Pin, OUTPUT);
  TC1_ConnectToPrescaler_8; //1 count = 0,5 µs
  TC1_ClearOnCompareMatchWithOCR1A;
  TC1_EnableInterruptOnCompareMatchWithOCR1A;
  OCR1A = 40000;
  for (byte i = 0 ; i<8 ; i++){
    CHX_Pulse[i] = 800 + i*200;
  }
}

void loop () {
}

ISR(TIMER1_COMPA_vect){
  digitalWrite(PPM_Pin, LOW);
  PPM_Progress = 1;
  OCR1B = 800;
  TC1_EnableInterruptOnCompareMatchWithOCR1B;
  return;
}

ISR(TIMER1_COMPB_vect){
  switch (PPM_Progress) {
    case 1: case 3: case 5: case 7: case 9: case 11: case 13: case 15: case 17:
      digitalWrite(PPM_Pin, HIGH);
      OCR1B = OCR1B + CHX_Pulse[PPM_Progress/2]*2;
      break;
    case 2: case 4: case 6: case 8: case 10: case 12: case 14: case 16:
      digitalWrite(PPM_Pin,LOW);
      OCR1B = OCR1B + 800;
  }
  PPM_Progress++;
  if (PPM_Progress == 18) {
    PPM_Progress = 0;
    TC1_DisableInterruptOnCompareMatchWith0CR1B;
  }
  return;
}
« Last Edit: August 21, 2012, 11:34:06 am by jan_huygh » Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks like a nasty problem. All I can guess is that the serial port initialisation is doing something necessary to the timer or interrupt configuration, which your subsequent use of interrupts depends on. But I have no idea what that something might be.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

USA
Offline Offline
God Member
*****
Karma: 14
Posts: 644
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Like PeterH, I suspect that the Serial.begin is causing something to be initialized a specific way that allows your code to be run.  Unfortunately, again like PeterH, I don't know what it is.  

However, your code seems to indicate you are comfortable with lower level control of the IC (like manipulating registers).  Therefore, if you don't get a response from someone more knowledgeable, my advice is to poke around the Serial library to see what exactly is being initialized then duplicate that in your code.  Then via experimentation and process of elimination you can figure-out what is enabling your program to work correctly and only include that in your final program.
Logged

Vilvoorde Belgium
Offline Offline
Newbie
*
Karma: 1
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The code now works... two things had to be done...
1) The array was incorrectly dimensioned in the beginning of the code (embarrassing)... I also changed the way the array is used in the OCR1B ISR.
2) In the OCR1A interrupt routine you needs to clear the interrupt. And to clear you need to write a 1 to the corresponding bit (so I write 255 to TIFR1) before you enable the interrupts again.

The now well working code
Code:
//Convenience macros
#define TC1_ConnectToPrescaler_8 TCCR1B &= ~((1<<CS12) | (1<<CS10)) ; TCCR1B |= (1<<CS11)
#define TC1_ClearOnCompareMatchWithOCR1A TCCR1A &= ~((1<<WGM11)|(1<<WGM10)); TCCR1B &= ~(1<<WGM13); TCCR1B |= (1<<WGM12)
#define TC1_EnableInterruptOnCompareMatchWithOCR1A TIMSK1 |= (1<<OCIE1A)
#define TC1_EnableInterruptOnCompareMatchWithOCR1B TIMSK1 |= (1<<OCIE1B)
#define TC1_DisableInterruptOnCompareMatchWith0CR1B TIMSK1 &= ~(1<<OCIE1B)

const byte PPM_Pin = 12;
volatile byte PPM_Progress = 0;
volatile word CHX_Pulse[8];

void setup () {
  pinMode(13,OUTPUT);
  pinMode(PPM_Pin, OUTPUT);
  TC1_ConnectToPrescaler_8; //1 count = 0,5 µs
  TC1_ClearOnCompareMatchWithOCR1A;
  TC1_EnableInterruptOnCompareMatchWithOCR1A;
  OCR1A = 40000;
  for (byte i = 0 ; i < 8 ; i++){
    CHX_Pulse[i] = 800 + i*200;
  }
}

void loop () {
}

ISR(TIMER1_COMPA_vect){
  digitalWrite(PPM_Pin, LOW);
  PPM_Progress = 1;
  OCR1B = 800;
  TIFR1 = 255;
  TC1_EnableInterruptOnCompareMatchWithOCR1B;
  digitalWrite(13,HIGH);
  digitalWrite(13,LOW);
  return;
}

ISR(TIMER1_COMPB_vect){
  switch (PPM_Progress) {
    case 1: case 3: case 5: case 7: case 9: case 11: case 13: case 15: case 17:
      digitalWrite(PPM_Pin, HIGH);
      OCR1B = OCR1B + CHX_Pulse[((PPM_Progress + 1)/2) - 1]*2;
      break;
    case 2: case 4: case 6: case 8: case 10: case 12: case 14: case 16:
      digitalWrite(PPM_Pin,LOW);
      OCR1B = OCR1B + 800;
  }
  PPM_Progress++;
  if (PPM_Progress == 18) {
    TC1_DisableInterruptOnCompareMatchWith0CR1B;
  }
  return;
}
Logged

USA
Offline Offline
God Member
*****
Karma: 14
Posts: 644
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great, I'm glad you got it working without all the extra overhead of the Serial library. smiley
Logged

South Texas
Offline Offline
Edison Member
*
Karma: 8
Posts: 1025
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial begin was creating a buffer that that you never used, bu that allocated memory kept your code from clobbering another value...
Logged

Pages: [1]   Go Up
Jump to: