Pages: [1]   Go Down
Author Topic: [RISOLTO]una semplice divisione che non funziona  (Read 431 times)
0 Members and 1 Guest are viewing this topic.
Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti
Sto impazzendo (sarà la stanchezza) ma proprio non capisco come mai questo semplice programmino non funzioni o meglio funzioni parzialmente.
è un semplice frequenzimetro che visualizza frequenza e periodo
Code:

#include <FreqCounter.h>


unsigned long frq;
int cnt;
int pinLed=13;
float per;
void setup() {
  pinMode(pinLed, OUTPUT);

  Serial.begin(9600);        

  Serial.println("Frequenzimtro");
  delay(2000);

}



void loop() {

  
  FreqCounter::f_comp=10;  
  FreqCounter::start(100);  

  while (FreqCounter::f_ready == 0)

  frq=FreqCounter::f_freq;
  per=(1/frq);

  Serial.print("  Freq: ");
  Serial.print(frq);
  Serial.println("Hz");
  Serial.print("  Periodo: ");
  Serial.print(per);
  Serial.println("s");
  delay(20);
  digitalWrite(pinLed,!digitalRead(pinLed));  

}  

il problema è che mi stampa correttamente la frequenza ma il periodo è sempre zero.
« Last Edit: October 18, 2012, 02:40:28 pm by BrainBooster » Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 103
Posts: 6588
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao Brain... è con piacere che ti invito a leggere qui --> http://arduino.cc/forum/index.php/topic,91560.0.html  smiley-twist smiley-twist

Almeno un link alla libreria che includi non sarebbe male.  smiley-roll-blue
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

preso  smiley-sweat
http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 103
Posts: 6588
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


FreqCounter.h
Code:
/*
  FreqCounter.h - Library for a Frequency Counter c.
  Created by Martin Nawrath, KHM Lab3, Dec. 2008
  Released into the public domain.
*/



#ifndef FreqCounter_h
#define FreqCounter_h


#include <avr/interrupt.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

namespace FreqCounter {

extern unsigned long f_freq;
extern volatile unsigned char f_ready;
extern volatile unsigned char f_mlt;
extern volatile unsigned int f_tics;
extern volatile unsigned int f_period;
extern volatile unsigned int f_comp;

void start(int ms);


}

#endif

FreqCounter.cpp
Code:
/*
  FreqCounter.cpp -
  Using Counter1 for counting Frequency on T1 / PD5 / digitalPin 5
  Using Timer2 for Gatetime generation

  Martin Nawrath KHM LAB3
  Kunsthochschule für Medien Köln
  Academy of Media Arts
  http://www.khm.de
  http://interface.khm.de/index.php/labor/experimente/
 
  History:
  Dec/08 - V1.0
  Oct/10 - V1.1    removed occasional glitches through interference with
  Jan/12 - V1.2    Arduino 1.0
  timer0
                   set intterrupt timebase to 1ms
                   works with atmega328

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <FreqCounter.h>

unsigned long FreqCounter::f_freq;

volatile unsigned char FreqCounter::f_ready;
volatile unsigned char FreqCounter::f_mlt;
volatile unsigned int FreqCounter::f_tics;
volatile unsigned int FreqCounter::f_period;
volatile unsigned int FreqCounter::f_comp;

void FreqCounter::start(int ms) {

#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)


    TIMSK0 &=~(1<<TOIE0);       // disable Timer0  //disable  millis and delay
    delayMicroseconds(50);      // wait if any ints are pending
   
    f_period=ms;
 
 
    if (f_comp ==0) f_comp=1;  // 0 is not allowed in del us

    // hardware counter setup ( refer atmega168.pdf chapter 16-bit counter1)
    TCCR1A=0;                  // reset timer/counter1 control register A
    TCCR1B=0;                 // reset timer/counter1 control register A
    TCNT1=0;               // counter value = 0
    // set timer/counter1 hardware as counter , counts events on pin T1 ( arduino pin 5)
    // normal mode, wgm10 .. wgm13 = 0
   
    TCCR1B |=  (1<<CS10) ;// External clock source on T1 pin. Clock on rising edge.
    TCCR1B |=  (1<<CS11) ;
    TCCR1B |=  (1<<CS12) ;
   
    // timer2 setup / is used for frequency measurement gatetime generation
    TCCR2A=0;
    TCCR2B=0;
   
    // timer 2 presaler set to 128 / timer 2 clock = 16Mhz / 256 = 62500 Hz
    TCCR2B |=  (1<<CS20) ;
    TCCR2B &= ~(1<<CS21) ;
    TCCR2B |=  (1<<CS22) ;

    //set timer2 to CTC Mode with OCR2A is top counter value
    TCCR2A &= ~(1<<WGM20) ;
    TCCR2A |=  (1<<WGM21) ;
    TCCR2A &= ~(1<<WGM22) ;
    OCR2A = 124;                // CTC divider by 125
   
    f_ready=0;                  // reset period measure flag
    f_tics=0;                   // reset interrupt counter
    GTCCR = (1<<PSRASY);        // reset presacler counting
    TCNT2=0;                    // timer2=0
    TCNT1=0;                    // Counter1 = 0
   
    TIMSK2 |=(1<<OCIE2A);       // enable Timer2 Interrupt
   
                                // External clock source on T1 pin. Clock on rising edge.
    TCCR1B |= (1<<CS12) | (1<<CS11) | (1<<CS10);        //   start counting now     
    #endif
}
//******************************************************************
//  Timer2 Interrupt Service is invoked by hardware Timer2 every 1ms = 1000 Hz
//  16Mhz / 128 / 125 = 1000 Hz
//  here the gatetime generation for freq. measurement takes place:

ISR(TIMER2_COMPA_vect) {
// multiple 2ms = gate time = 100 ms
if (FreqCounter::f_tics >= FreqCounter::f_period) {         
                            // end of gate time, measurement ready

    // GateCalibration Value, set to zero error with reference frequency counter
    //  delayMicroseconds(FreqCounter::f_comp); // 0.01=1/ 0.1=12 / 1=120 sec
    delayMicroseconds(FreqCounter::f_comp);
    TCCR1B = TCCR1B & ~7;    // Gate Off  / Counter T1 stopped
    TIMSK2 &= ~(1<<OCIE2A);    // disable Timer2 Interrupt
    TIMSK0 |=(1<<TOIE0);      // enable Timer0 again // millis and delay
    FreqCounter::f_ready=1;             // set global flag for end count period
   
                                        // calculate now frequeny value
    FreqCounter::f_freq=0x10000 * FreqCounter::f_mlt;  // mult #overflows by 65636
    FreqCounter::f_freq += TCNT1;      // add counter1 value
    FreqCounter::f_mlt=0;
   
    }
    FreqCounter::f_tics++;            // count number of interrupt events
    if (TIFR1 & 1) {          // if Timer/Counter 1 overflow flag
    FreqCounter::f_mlt++;               // count number of Counter1 overflows
    TIFR1 =(1<<TOV1);        // clear Timer/Counter 1 overflow flag
    }
    // PORTB = PORTB ^ 32;  // int activity test
}

Secondo me dovresti spostare l'inizializzazione nel setup e non ripeterla ogni loop
Code:
FreqCounter::f_comp=10;   
  FreqCounter::start(100); 

e poi fare
Code:
per=(float)(1.0/frq);
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

facendo come hai detto non mi stampa più neanche la frequenza smiley-razz
Logged

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

continuo a non capire perchè a divisione non funziona ma comunque grazie a PaoloP ho notato che il periodo viene esportato (se non ho capito male)e quindi ho provato a cambiare il codice come segue
Code:

#include <FreqCounter.h>


unsigned long frq;
int cnt;
int pinLed=13;
unsigned int per;
void setup() {
  pinMode(pinLed, OUTPUT);

  Serial.begin(9600);       

  Serial.println("Frequenzimtro");
  delay(2000);
 
}



void loop() {

 
  FreqCounter::f_comp=10;   
  FreqCounter::start(100);

  while (FreqCounter::f_ready == 0)

  frq=FreqCounter::f_freq;
  per=FreqCounter::f_period;

  Serial.print("  Freq: ");
  Serial.print(frq);
  Serial.println("Hz");
  Serial.print("  Periodo: ");
  Serial.print(per);
  Serial.println("ms");
  delay(20);
  digitalWrite(pinLed,!digitalRead(pinLed)); 




il risultato è che adesso mi stampa il periodo ma non è il valore atteso, stampa sempre 100
edit: che fesso.. è il periodo di campionamento, quindi torniamo al codice iniziale
« Last Edit: October 18, 2012, 02:05:03 pm by BrainBooster » Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9185
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

l problema è che mi stampa correttamente la frequenza ma il periodo è sempre zero.

Perché la serial.print di default stampa solo due decimali e sicuramente il periodo è sotto questo limite.
Devi usare la serial.print(valore, n) ove n è il numero di decimali da stampare.
Logged

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

no, astro grazie della risposta
ma quel periodo non è il valore che cerco.
Voglio solo fare il calcolo del periodo dalla frequenza, tutto qui.
ma sembra che la divisione (1/frequenza) non gli piaccia e non capisco perché
Logged

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ho fatto una prova stupida che però ha funzionato...
Per prova ho scambiato la divisione con una moltiplicazione e mi stampa il numero aspettato
Code:

#include <FreqCounter.h>


unsigned long frq;
int cnt;
int pinLed=13;
float per;
void setup() {
  pinMode(pinLed, OUTPUT);

  Serial.begin(9600);       

  Serial.println("Frequenzimtro");
  delay(2000);

}



void loop() {

 
  FreqCounter::f_comp=10;   
  FreqCounter::start(100); 

  while (FreqCounter::f_ready == 0)

  frq=FreqCounter::f_freq;
  per=(1.00*frq);                        //<-errore voluto, scambiato il "/" con il "*"

  Serial.print("  Freq: ");
  Serial.print(frq);
  Serial.println("Hz");
  Serial.print("  Periodo: ");
  Serial.print(per);
  Serial.println("s");
  delay(20);
  digitalWrite(pinLed,!digitalRead(pinLed)); 



quindi l'ide 1.0.1 cel'ha con le divisioni ?!  smiley-yell
Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9185
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

ma sembra che la divisione (1/frequenza) non gli piaccia e non capisco perché

Non hai capito, se f = 1000 il periodo è 1/1000 = 0.001 e la serial.print ti stampa 0 perché sei fuori dal numero di decimali di default.
Logged

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

come al solito hai ragione
bastava fare
Serial.print(per,6);
Grazie smiley-wink
Logged

Pages: [1]   Go Up
Jump to: