Go Down

Topic: Im at a dead end... (Read 433 times) previous topic - next topic

devasri

Nov 10, 2017, 06:26 pm Last Edit: Nov 10, 2017, 06:31 pm by devasri
We want the duty cycle of the pwm out to be proportional to the delay in timing of both square signals, if its leading it will output on one ocr pin if it is lagging, it goes to the other, based on which value comes first. Also we have to wait for the program to change both values of the signals, PORTA and PORTB, to compare the delay, which i think its not doing correctly. for testing purposes we're inputting 1 hz square waves so we can see the output, but for the real deal it should be 40khz square waves, but its not working, and I am also not great with arduino (my first time) I am not sure why our code isn't working properly. Is there another way to do this or what should we try and change? Thanks!
Code: [Select]
#include <avr/io.h>
#include <avr/interrupt.h>
#define CLK 16000000UL

bool t1_changed = false;
bool t2_changed = false;

void setup() {
 // Serial.begin(115200);
  noInterrupts();
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(CS22);
  OCR2A = 0;
  OCR2B = 0;
  TCNT2 = 0;
  //TIMSK2 |= (1 << TOIE2);
  interrupts();

  attachInterrupt(0, t1_ISR, RISING);     //enable interrupt service routines on pins 2 and 3
  attachInterrupt(1, t2_ISR, RISING);
}

volatile unsigned int t1;
volatile unsigned int t2;
//volatile unsigned int oldt1, oldt2;

void loop() {
 // noInterrupts();
 
  //noInterrupts();
  //t1_changed = false;
  //t2_changed = false;
 PORTC=PORTB-PORTA;
 
    if(SREG & 4)
    {
      OCR2A = (PORTB ^ PORTA);   //duty cycle   50%
      OCR2B = 0;
    }
    else if(PORTA == PORTB)
    {
      OCR2A = 0;
      OCR2B = 0;
    }
    else
    {
      OCR2A = 0;
      OCR2B = (PORTA ^ PORTB);
      //OCR2A = 0;
    }
    cli();
 // t1_changed=true;
  //t2_changed=true;
  //interrupts();
}

void t1_ISR()
{
  //Serial.println("ISR");
  PORTA = TCNT2;
  //t1_changed = true;
   Serial.println("PORTA is:");
   Serial.println(PORTA);
  //oldt1=t1;
}

void t2_ISR()
{
  //Serial.println("ISR2");
  PORTB = TCNT2;
 // t2_changed = true;
    Serial.println("PORTB is:");
    Serial.println(PORTB);
 // oldt2=t2;
}

Delta_G

That's an awful lot of bare-metal code for a first timer.  Nothing like jumping straight into the deep end and relying on the lifeguards to save you. 

Don't do serial stuff inside your ISR.  Serial relies on interrupts that are turned off during your ISR. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Delta_G

#2
Nov 10, 2017, 06:30 pm Last Edit: Nov 10, 2017, 06:30 pm by Delta_G
Code: [Select]
PORTC=PORTB-PORTA;

What are you thinking this line will do?  I doubt it does what you think. But it's hard to tell what you expected. 

Similarly with this one, what do you expect to have happen with this?

Code: [Select]
PORTA = TCNT2;
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Robin2

#3
Nov 10, 2017, 07:27 pm Last Edit: Nov 10, 2017, 07:29 pm by Robin2
You should be aware that not all the pins on a Port are available to you. Some of the pins have special functions and you should take care not to change them.

If you use the digitalWriteFast library it is almost as fast as port manipulation and it makes code a lot easier to understand.


...R
Two or three hours spent thinking and reading documentation solves most programming problems.

wvmarle

PORTA and PORTB are complete 8-bit registers, handling multiple ports.
I suppose you are interested in reading only two specific pins, so you have to look into reading those specific bits.

Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

devasri

I changed those to regular variables as well, but the timers still don't sync, so the comparison is always off for the time delay we need as the pwm duty cycle
Code: [Select]
#include <avr/io.h>
#include <avr/interrupt.h>

bool t1_changed = false;
bool t2_changed = false;

void setup() {
  Serial.begin(115200);
  noInterrupts();
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(CS22);
  OCR2A = 0;
  OCR2B = 0;
  TCNT2 = 0;
  interrupts();

  attachInterrupt(0, t1_ISR, RISING);     //enable interrupt service routines on pins 2 and 3
  attachInterrupt(1, t2_ISR, RISING);
}

volatile unsigned int t1;
volatile unsigned int t2;
//volatile unsigned int oldt1, oldt2;

void loop() {
 
  while(!(t1_changed && t2_changed))
 {
  Serial.println(t2 ^ t1);
  noInterrupts();
  t1_changed = false; t2_changed = false;
 
    if(t1 < t2)
    {
      OCR2A = t2 ^ t1;   //duty cycle   50%
      OCR2B = 0;
    }
    else if(t2 < t1)
    {
      OCR2B = t1 ^ t2;
      OCR2A = 0;
    }
 // t1_changed=true;
  //t2_changed=true;
  interrupts();
}}

void t1_ISR()
{
  //Serial.println("ISR");
  t1 = TCNT2;
  t1_changed = true;
   // Serial.println(t1);
  //oldt1=t1;
}

void t2_ISR()
{
  //Serial.println("ISR2");
  t2 = TCNT2;
  t2_changed = true;
   // Serial.println(t2);
 // oldt2=t2;
}

Robin2

You can't do this
Code: [Select]
  while(!(t1_changed && t2_changed))
because both variables occupy two bytes and part of the value could be changed by the ISR while you are reading the values

Do it like this
Code: [Select]
if (t1_changed == true) {
  noInterrupts();
   t1Copy = t1;
   newT1Copy = true; // not sure if this is needed
   t1_changed =  false;
  interrupts();
}
if (t2_changed == true) {
  noInterrupts();
   t2Copy = t2;
   newT2Copy = true;
   t2_changed =  false;
  interrupts();
}

and then in the rest of your code use t1Copy and t2Copy

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

devasri


Go Up