Progetti

   

Tutorial

   

Servizi

   
Benvenuto, Ospite
Nome utente: Password: Ricordami
  • Pagina:
  • 1
  • 2

ARGOMENTO: Utilizzo modulo PWM per generare segnali analogici

ltlib uart e interrupt 2 Mesi 1 Settimana fa #1

  • marcoilgrande
  • Avatar di marcoilgrande
  • Offline
  • Fresh Boarder
  • Messaggi: 14
  • Karma: 0
Ciao a tutti, riassillo di nuovo il forum... ho provato a riaddattare il codice pwm per far suonare un buzzer ma non suona come dovrebbe. Allego codice, ammetto di aver preso spunti su internet
#include <xc.h>
 
//#include "PIC18F4550_config.h"
#include "LTlib.h"
 
#include "LTlib_delay.h"
#include "LTlib_delay.c"
 #define XF      20000000
#define _XTAL_FREQ      20000000
#define TMR2PRESCALE    16
 
// TONES  ==========================================
#define  c     261
#define  d     293
#define  e     329
#define  f     349
#define  g     392
#define  a     440
#define  b     493
#define  C     523
#define  D     587
#define  E     659
#define  F     698
#define  G     784
// Define a special note, 'R', to represent a rest
#define  R     0
// ==================================================
 
int tempo = 2000;
 
int current_tone = 0; //current playing note
int current_tone_duration = 0; //current note duration
 
 
void SetupClock() {
//    OSCCONbits.IRCF = 0b110; //set internal oscillator to 4 Mhz
//    OSCCONbits.SCS = 0b00; //use oscillator defined by FOSC
}
 
void PWM1_Init(long desired_frequency) {
 
//    1 - Definire e scrivere nel registro PR2 del pic, il periodo del PWM
//2 - Definire il modulo CCPx come PWM
//3 - Abilitare il timer TMR2 ed il suo prescaler opportunamente scelto in funzione del periodo
//4 - Definire il duty cycle del segnale generato.
//
//Queste 4 operazioni possono essere scritte più o meno semplicemente in funzione del linguaggio usato. Ma anche se scritte in Assembler, non sono molto faticose. Io solitamente uso il "C" della CCS e basta una riga per operazione, grazie anche alle built in function del compilatore.
//Come esempio ipotizziamo di usare CCP2 con uscita su RC1.
//Dovremo stabilire per prima cosa il periodo del nostro segnale.
//periodo PWM =[(PR2)+1]*4*Tosc*(TMR2 prescale value)
//dove: - TMR2 prescale value è il valore di prescaler associato al Timer2 del 16f877 - PR2 è un registro (associato a Tmr2) da impostare con opportuno valore per ottenere il periodo voluto - Tosc è l’inverso della frequenza del quarzo esterno che fornisce il clock al PIC TMR2 prescale value può valere 1, 4, 16 e PR2 è un registro a 8 bit pertanto il valore deve essere compreso tra 0 e 255. Usando CCS come compilatore scriverei:
//
//          setup timer_2(T2_DIV_BY_1,99,1);
//          setup CCP2( CCP_PWM);
//          setpwm2_duty (200); 
 
    PR2 = (XF / (desired_frequency * 4 * TMR2PRESCALE)) - 1; //(XF / (desired_frequency * 4 * TMR2PRESCALE)) - 1;
    current_tone = desired_frequency;
}
 
int PWM_Max_Duty() {
    return (XF / (current_tone * TMR2PRESCALE));
}
 
void PWM1_Duty(unsigned int duty) {
 
//    CCPR1L = (unsigned char) (duty >> 2);
// 
//    if (duty & 0x0001)
//        CCP1CONbits.DC1B0 = 0x0001;
//    else
//        CCP1CONbits.DC1B0 = 0x0000;
// 
//    if (duty & 0x0002)
//        CCP1CONbits.DC1B1 = 0x0001;
//    else
//        CCP1CONbits.DC1B1 = 0x0000;
    if (duty < 1024) {
        duty = ((float) duty / 1023) * PWM_Max_Duty();
         DC1B1 = duty & 2; //CCP1X = duty & 2;
         DC1B0 = duty & 1; // CCP1Y = duty & 1;
        CCPR1L = duty >> 2;
    }
}
 
void PWM1_Mode_On() {
    CCP1M3 = 1;
    CCP1M2 = 1;
}
 
void PWM1_Start() {
    PWM1_Mode_On();
 
#if TMR2PRESCALE == 1
    T2CKPS0 = 0;
    T2CKPS1 = 0;
#elif TMR2PRESCALE == 4
    T2CKPS0 = 1;
    T2CKPS1 = 0;
#elif TMR2PRESCALE == 16
    T2CKPS0 = 1;
    T2CKPS1 = 1;
#endif
    TMR2ON = 1;
}
 
void PWM1_Stop() {
    CCP1M3 = 0;
    CCP1M2 = 0;
}
 
void playTone() {
    //TODO: The Tone R is not implemented yet.
    if (current_tone > 0) {
        PWM1_Init(current_tone);
        PWM1_Duty(511);//511);
 
        delay_ms(current_tone_duration);
        PWM1_Duty(0);
    }
}
 
int main(int argc, char** argv) {
    short melody[] = {g, g, a, g, C, b, g, g, a, g, D, C, g, g, G, E, C,
        b, a, F, F, E, C, D, C};
    char beats[] = {8, 8, 4, 4, 4, 2, 8, 8, 4, 4, 4, 2, 8, 8, 4, 4, 4,
        4, 4, 8, 8, 4, 4, 4, 2};
//           short melody[] = {E,F,G,G,E,F,G,G,E,F,G,E,F,G,G,E,F,G,G,G,F,F,E};
//    char beats[] = {2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4};
//    
 
    char MELODY_LENGTH = sizeof (melody) / sizeof (melody[0]);
 
    SetupClock();
    TRISCbits.TRISC2 = 0; //set Pin B3 as output
    PORTC = 0x00;
 
 
 
    PWM1_Init(500); //exact value doesn't matter at all, just not 0
    PWM1_Duty(0);
    PWM1_Start();
 
    while (1) {
        for (int i = 0; i < MELODY_LENGTH; i++) {
            current_tone = melody[i];
            current_tone_duration = tempo / beats[i];
 
            playTone();
            delay_ms(tempo/200);
        }
        delay_ms(2000);
    }
    return 0;
}


Grazie a tutti in anticipo! Purtroppo codici xc8 per buzzer pic18 non se ne vedono nemmeno in giro
Ultima modifica: 2 Mesi 6 Giorni fa da marcoilgrande.
L\'Amministratore ha disattivato l\'accesso in scrittura al pubblico.

ltlib uart e interrupt 2 Mesi 5 Giorni fa #2

  • Mauro Laurenti
  • Avatar di Mauro Laurenti
  • Offline
  • Moderatore
  • Messaggi: 4476
  • Ringraziamenti ricevuti 515
  • Karma: 49
Salve Marco,

prima di entrare nei dettagli del software:
  • Qual'è lo schema elettrico che usi?
  • Quando dici che non suona come dovrebbe, che senti?

Con una singola nota funziona?

Saluti,

Mauro
L\'Amministratore ha disattivato l\'accesso in scrittura al pubblico.

ltlib uart e interrupt 2 Mesi 5 Giorni fa #3

  • marcoilgrande
  • Avatar di marcoilgrande
  • Offline
  • Fresh Boarder
  • Messaggi: 14
  • Karma: 0
suona ma il suono é parecchio acuto. Se invece configuro il pic con un oscillatore interno i toni hanno la tonalità giusta. Boh, nn ne capisco il perche.

Il circuito é uno di quelli preassemblati che vendono su ebay compatibili pic e arduino. Si vede un transistor in smd e una resistenza. Il tutto è su rc1 o rc2, nn ricordo, é luscita pic ccp1 del 18f4550
Ultima modifica: 2 Mesi 5 Giorni fa da marcoilgrande.
L\'Amministratore ha disattivato l\'accesso in scrittura al pubblico.

ltlib uart e interrupt 2 Mesi 3 Giorni fa #4

  • marcoilgrande
  • Avatar di marcoilgrande
  • Offline
  • Fresh Boarder
  • Messaggi: 14
  • Karma: 0
Credo dipenda tutto dal timer.L'esempio è calibrato per 4 mhz. ho provato a portarlo a 20 ma non so bene dove operare. Presuno su PR2 ma non cambia nulla, forse bisogna toccare PWM_Max_Duty o forse su altro.

BOH
L\'Amministratore ha disattivato l\'accesso in scrittura al pubblico.

ltlib uart e interrupt 1 Settimana 1 Giorno fa #5

  • marcoilgrande
  • Avatar di marcoilgrande
  • Offline
  • Fresh Boarder
  • Messaggi: 14
  • Karma: 0
Nessuno mi sa aiutare?
L\'Amministratore ha disattivato l\'accesso in scrittura al pubblico.
  • Pagina:
  • 1
  • 2
Moderatori: Mauro Laurenti, Pinna, StefA, Matteo Garia
Powered by Forum Kunena
   
© LaurTec 2006-2015