Hallo,
Om het aantal keren dat een signaal aankomt op RA0 te tellen en uit te zetten in de tijd (per seconde) probeer ik een oplossing te maken.
De bedoeling is om gebruik te maken van de interne clock van de PIC. Dus niet werken met delay(xsec). Op de 'achtergrond' moet de PIC tellen hoe vaak het signaal is gekomen [RA0 = 1]. Wanneer één seconde voorbij is presenteert deze de waarde en wordt de 'storage' of geheugenplaats gewist. En zo elke seconde herhalen.
Ik heb een LCD-scherm deze werkt, daarop wordt de waarde gepresenteerd.
Mijn PIC: 16F628a
Tooling: C-Code
do {
//RPM_Value++;
if(PORTA.RA0 == 1)
{
RPM_Value = timeInt;
}
Value = (256*countLo + countHi)*60;
Display_Value(Value);
}while(1);
}asm {
btfss INTCON,INTF; //Als interrupt...
//btfss TRISA,0; //PORTA.RA0 lezen
goto noValue;
incfsz _countLo; //Hoog op bij een 'laag' signaal RA0=0
goto clearValue;
incf _countHi; //Hoog op bij een 'hoog' signaal RA0=1
clearValue:
bcf INTCON,INTF; //Leeg interrupt...
//bcf TRISA,0; //Legen f...
noTach:
btfss INTCON,T0IF; //Als interrupt...
//btfss TRISA,T0IF; //Als interrupt...
goto noTimer;
decfsz _sec; //Verlaag seconden met 1
goto clearTimer;
movlw 1
movwf _timeInt; //Geef signaal aan timer interrupt
movlw 50
movwf _sec; //Stel de timer opnieuw in
clearTimer:
bcf INTCON,T0IF; //Leeg timer interrupt...
//bcf TRISA,T0IF; //Leeg timer interrupt...
noTimer:
}Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Beter portb gebruiken, die heeft IOC. Dan krijg je bij iedere verandering een interrupt.
Dat maakt de zaak een stuk simpeler.
Arco: Ik heb dit gedaan, maar zie countHi of countLo niet oplopen.
De bedoeling is dat ik een interrupt op RB1 afvang en dat deze in countLo en countHi worden opgeslagen (tot tellingen per seconde).
Wie heeft een stukje code of een begin voor mij waar een interrupt (op de achtergrond, dus los van de while(1) lus wordt bijgehouden in een variabele die weer in de loop is uit te lezen. Ik vermoed dat dit in ASM moet. (In Java kun je Threading gebruiken
)
benleentje
Golden Member
Gebruik hiervoor een timer interupt. Stel de divider voor de timer zo hoog mogelijk en gebruik die als een 10mS klok, afhankelijk van je gebruikte cristal. Als je 100 keer een 10mS interrupt hebt gehad heb je precies 1 seconde.
Zoek eens op internet voor een frequentieteller met een PIC.
[Bericht gewijzigd door benleentje op (12%)]
Ik heb nu:
void interrupt() {
// Increment value of countHi on every interrupt
plusCounter(1);
if(INTCON.INTF=1)
{
plusCounter(1);
RB0_bit=0;
INTCON.INTF=0; // Reset the external interrupt flag
}
}
void plusCounter(int c)
{
countHi = countHi +1;
}
Alleen merk ik dat de variabele countHi niet verhoogt. Ook merk ik dat met
UART1_Write(countHi);geen waarden teruggegeven kunnen worden. Alleen ASCII waarden.
benleentje
Golden Member
Van c code weet ik niet heel veel maar in je routine pluscounter roep je die nog een keer op (regel boven Rb=0
Ook ben je nu aan het pollen of de interrupt geldig is ipv dat je de hardware zelf het werk laat doen.
Een seconde maak je daar een heleboel keer een timer interrupt te genereren met een tijd van bv 5mS moet je dat 200 keer doen.
De interrupt op je input pin tel je gewoon en na 1000mS heb je dan 200 timer interrups gehad en kan je het getelde aantal weergeven.
Overigens kan je ook de getelde hoeveel van 5mS weergeven door dat x 200 te doen.
Heb je al op Frequency Counter gezocht ?
Ja ik heb op frequency counter gezocht.
Heb nu wel dat ik de Byte naar String kan zetten. Dit werkt goed, alleen de interrupt afvangen en CNT+1 zetten lukt nog niet.
ByteToStr(CNT, txtBPM); // convert BPM to string
UART1_Write_Text(txtBPM);En interrupt heb ik nu twee controles:
if(INTCON.INTF=1)
{
plusCounter(1);
RB0_bit=0;
INTCON.INTF=0; // Reset the external interrupt flag
}
if(INTCON.RBIF == 1 && PORTB.B0 != 0){ // check RB0 upon rising edge
CNT = timer1; // Copy timer1 value to CNT
timer1= 0 ; // reset timer1 value
}
INTCON.RBIF = 0; // Clear RB interrupt flag at rising edge AND at falling edge
benleentje
Golden Member
void plusCounter(int c)
{
CNT = CNT +1;
}
Deze telt bij de variabele CNT + 1 op. Dit tijdens elk interrupt op RB0 (tenminste dat zou hij moeten doen. Maar de interrupt op RB0 wordt nooit afgevangen. Ik heb nu een puls van 0-5V met een freq van 50Hz op RB0 staan. Deze zou toch interrupt moeten geven.
Hij doet iets....alleen ik zie dat cnt nooit > dan 255 wordt. Dus zal een teller bij moeten gaan houden. Om te kijken hoe vaak hij de grens over is gegaan. Dan weet ik het aantal signalen op RB0.
//
// Counter
//
const unsigned char VersionString1[]="V1.00";
const unsigned char VersionString2[]="18/05/2011";
#include "RevCount-vars.h"
//MAIN
//
char i; // Loop variable
unsigned long Timems;
unsigned short BPM;
char txtBPM[6],txtTimems[6];
unsigned int Timer1 at TMR1L;
volatile unsigned int CNT = 0;
volatile unsigned short DisplayBPMflag = 0;
void interrupt(){
if(INTCON.INTF == 1 ){
countHi++; // Increment variable cnt
cnt = countHi; //(256*Timer1)*60;
INTCON.INTF = 0; // Clear Interrupt Flag
}
}
void main()
{
TMR0 = 0; // Timer0 initial value
TRISB = 0x01; // Set PB0 as input
TRISA = 0x00; // Set PortD as output
PORTA = 0x00; // Starting value for PortA
INTCON = 0x90; // Interrupt flags:
//Enable Global Interrupt
//Enable External Interrupt
//WPUB = 0x01; // Weak Pull-Up on pin B0
Delay_ms(1000);
UART1_Init(9600); // initialize USART module
// (8 bit, 9600 baud rate, no parity bit...)
UART1_Write_Text("Demo program");
Delay_ms(100);
UART1_Write_Text(";");
while (1) {
UART1_Write_Text("[");
//WordToStr(timems, txtTimems); // convert Timems to string
ByteToStr(CNT, txtBPM); // convert BPM to string
UART1_Write_Text(txtBPM);
UART1_Write_text("]"); // send data via USART
Delay_ms(400);
UART1_Write_Text(";");
PORTA = cnt;
}
}
[Bericht gewijzigd door Henry S. op (75%)]
stecj366
Sonar is meer dan Ping...
Dat kan aan een aantal dingen liggen:
1) hoeveel bit is een int in je C implementatie? Maak er eens een long int van
2) More likely: de functie bytetostr() zegt al zelf: converteer een byte naar een string. Dat kan dus niet echt werken: je gaan een byte (max 255) converteren naar een string. Krijg je geen warning bij je compiler dat je een int meegeeft aan een byte functie?
heb je geen inttostr, of wat geeft die wordtostr?
Ja de IntToStr werkt beter
) Keek er gewoon overheen. Thanx Stecj!
Ben nu een counter aan het bijhouden die het aantal keren dat RB0 een interrupt krijgt te tellen. Deze probeer ik te matchen met een timer (Timer1). Dan kan ik het aantal keren dat RB0 aan/uit gaat in de tijd uitzetten. Bijvoorbeeld per seconde.
De interrupt is niet constant. Bij 50Hz = de telling instabiel. + of -21. Het valt wel op dat de waarden rond een mediaan zitten.
Bij 200Hz input op RB0 worden de verschillen groter en zakt de waarde. Je verwacht een recht evenredig verband.
Nu kristal 20MHz. + delay in while(1) loop van 100ms. En vermenigvuldig de waarde met 600 en voila. Alleen bij hogere frequenties oogt de PIC trager.
[Bericht gewijzigd door Henry S. op (39%)]
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Stel je wil de 50Hz van het net meten. Stel je seconde is precies 1 sec, maar het net draait op 50.5Hz. Dan zal je de ene seconde 50 en de volgende 51 interrupts krijgen.
Als je de RPM wilt gaan meten, dan moet je dus nog vermenigvuldigen met 60. Dat zorgt er voor dat je toerental behoorlijk staat te schommelen. Wat kan je hieraan doen?
Wat je kan doen is de seconde pas in laten gaan precies op een pulsje, en dan van de eerste puls NA de seconde de tijd meten. Dus als je dan het 52e pulsje hebt op 1.010 sec kom je precies op de 50.5Hz.
Een waarschuwing voor de TS wegens regelmatig topickicken (ook in andere topics), gebruik de edit bij toevoegingen.
srry da ik over iets anders begin maar weet iemand hoe da ge de rimpelspanning moet berekenen als ge gene stroom hebt gemeten?
Topickapen is niet toegestaan, open een eigen topic. In normaal Nederlands aub.