Problem med PWM och triangel/sinusvåg

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
sebgus
Inlägg: 408
Blev medlem: 11 december 2007, 09:51:17
Ort: Göteborg

Problem med PWM och triangel/sinusvåg

Inlägg av sebgus »

Tjenare!

Försökt att få till sinus/triangel-vågor på min PIC genom att använda PWM:n som en DA-omvandlare (tillsammans med en RC-krets).

Det är en PIC16F887 som går i 8Mhz, RC2 (Timer2s period-register) = 127, TMR2prescale = 4.

Detta borde ju generera en periodtid på PWM:n på 256 µs, inte sant? (T = (127 + 1) * 4 * (1/8000000) * 4 = 256 µs)

RC-kretsen ska vara ungefär 40 ggr större än denna periodtid (för att medelvärdesbilda), valde därför R = 10 kohm, C = 1 µs (ellyt).

Men allt jag får på utgången är detta:

Och med en annan RC-krets, detta:

Vad gör jag för fel? :)

EDIT: Nu funkar första filmen!
Senast redigerad av sebgus 5 februari 2010, 20:44:06, redigerad totalt 1 gång.
Användarvisningsbild
E85
Inlägg: 1274
Blev medlem: 29 maj 2007, 16:24:19
Ort: Övik

Re: Problem med PWM och triangel/sinusvåg

Inlägg av E85 »

Och var är koden för att generera triangelvågen? Tycker det ser ut som den sveper pulsbredden alldeles för sakta.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sodjan »

> Vad gör jag för fel?

För det första att försöka använda YouTube för att visa vad du gör.
(Och det är bara en av dom som fungerar)
Varför inte bara visa ett par vanliga bilder ?

För det andra har du inte talar om vad som är problemet !
Den ena filmen visar ju en kurva. Är den inte OK ?

För det tredje så fungerar nog inte det du försöker göra i alla fall.
Användarvisningsbild
sebgus
Inlägg: 408
Blev medlem: 11 december 2007, 09:51:17
Ort: Göteborg

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sebgus »

Naturligtvis ska vi ha koden också! Tack för att du påminde mig :)

Den är kanske inte är så städat, men här kommer den:

Kod: Markera allt

#include <pic16F887.h>
#include	<math.h>

double x, j, y;

unsigned char ad8bit(unsigned char kanal);

void main() {
	PWM1CON=0x07;
	TRISD=0xFF;
	TRISC=0x00;
	PR2=0x7F;
	CCP1CON=0x0C;
	TMR2ON=1;
	T2CKPS0 = 1;
	T2CKPS1 = 0;
	ADCON0=0xC1;

	while(1){
		x=0;
		y=0;
		while(x<(2*3.14)){
		x = x+0.1;
		y=sin(x)+1;
		y = y*64;
		y = 40+(y*34);
		CCPR1L=(unsigned char)y;
	}
}

unsigned char ad8bit(unsigned char kanal){
	kanal<<=3;
	ADCON0=0xC1 | kanal;
	Delay(100);
	GODONE=1;
	while(GODONE);
	return ADRESH;
}

Användarvisningsbild
sebgus
Inlägg: 408
Blev medlem: 11 december 2007, 09:51:17
Ort: Göteborg

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sebgus »

sodjan skrev:> Vad gör jag för fel?

För det första att försöka använda YouTube för att visa vad du gör.
(Och det är bara en av dom som fungerar)
Varför inte bara visa ett par vanliga bilder ?

För det andra har du inte talar om vad som är problemet !
Den ena filmen visar ju en kurva. Är den inte OK ?

För det tredje så fungerar nog inte det du försöker göra i alla fall.
Varför jag inte ville ta ett par bilder var för att det inte visas lika bra som på film. Ska försöka fixa den första filmen!

Det jag vill ha är en ren och stabil triangelvåg som inte håller på att ändra sig upp och ner som denna gör.

Hur vet du att det inte funkar? Har gjort det i skolan med ungefär samma kod och hårdvara, så varför skulle det inte funka för mig här hemma?
Användarvisningsbild
E85
Inlägg: 1274
Blev medlem: 29 maj 2007, 16:24:19
Ort: Övik

Re: Problem med PWM och triangel/sinusvåg

Inlägg av E85 »

Ja men tryck dit en lite fetare kondning och öka PWM-frekvensen så borde det väl bli bättre.
Sen så brukar man använda en lookuptabell för sinuskurvor för att det blir mycket snabbare.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sodjan »

Vad förväntar du dig att den där koden ska göra ?
Vilken cykeltid har du i koden ? Har du kört någon
simulering med alla sin() och mul/div med udda värden ?
Var används ad8bit() ?
Min gissning är att hela lösningen är uppåt väggarna.

> Hur vet du att det inte funkar?

Hur *jag* vet det ?? Du sa ju inget i första inlägget om
vad du förvänatde dig, och då går det ju inte att avgöra
om det du visade var rätt eller fel.

> Har gjort det i skolan med ungefär samma kod och hårdvara,

Och vad betyder mer exakt "ungefär" ?
Om du har en lösning som fungerar och så fungerar inte "ungefär"
samma lösning, så skulle jag leta efter felet i det som utgör "ungefär"...
Användarvisningsbild
sebgus
Inlägg: 408
Blev medlem: 11 december 2007, 09:51:17
Ort: Göteborg

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sebgus »

Sodjan:

Jag uppskattar att du försöker hjälpa till, men om du ska komma med dryga svar och allmän bitterhet så kan du lika gärna sluta skriva i tråden.

Som jag skrev så är inte koden riktigt städat (ad8bit() används inte t.ex.), men det är inget som ska påverka resultatet.

Anledningen till varför jag skrev ungefär var för att jag inte har 2000 krs programmerare (och tillgång till dyrare mätinstrument) eller samma kompilator. Har varit tvungen att ändra lite småsaker, men inget större. Därav ungefär!

Min gissning är att det inte är helt uppåt väggarna, bara något skitfel som ligger någonstans som jag inte kan se/upptäcka.

E85:

Tackar, ska ta en titt på detdär med frekvensen och lookup-tabellen.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sodjan »

> Som jag skrev så är inte koden riktigt städat (ad8bit() används inte t.ex.),

Då ska den *ABSOLUT* inte finnas med i kod som postas här.
Det är ju kollosalt slappt inte att redigera bort den innan, det är
ju bara ca 30 rader totalt. Jag funderade antagligen längre tid på vad
ADC'n hade med det hela att göra än vad det hade tagit dig att
städa koden. Slappt är bara förnamnet...

> men det är inget som ska påverka resultatet.

Kanske inte, men det påverkar svaren du får.

Du talar också om både sinus och triangelvåg, men den där koden
är väl bara tänkt att generera en av dom ? Är det kanske sinus
varianten med tanke på sin() funktionen ?

Sen så ser lösning som sagt lite underlig ut med alla beräkningar.
Normalt löser man liknande problem med förberäknade lookup tabeller,
speciellt om man ska ha någon slags trigonometriska värden. Om koden
ser ut så där för en mikrokontroller så finns det all anledning att
fundera på lösningen en extra gång.

> ...Har varit tvungen att ändra lite småsaker,...

OK. Då är ju fortfarande det intressanta vad dessa "småsaker" är.
Om du har en fungerande lösning, och sedan ändrar några "småsaker"
och så lägger det av, så är det ju ganska naturligt att leta efter problemet
bland just de "småsakerna" som är ändrade.

> Jag uppskattar att du försöker hjälpa till,

Tack ! :-) Det är alltid lika roligt. Inga problem alls...
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Problem med PWM och triangel/sinusvåg

Inlägg av jesse »

Uppåt väggarna?: Vad Sodjan kanske menar är att du kör med alldeles för få decimaler. Du måste använda long double för att få tillräcklig noggrannhet med den processorn. :roll: (obs! skämt)

eller... tvärt om kanske: flyttal tar enorm tid att beräkna och risken är mycket stor att din processor inte hinner beräkna värdena som behövs i din kurva. Prova med heltal och undvik onödiga matematiska funktioner som sin() eller onödig division.. så kanske det blir bra.

Om du absolut vill använda flyttal så byt double mot float (om det är kortare?), beräkningstiden minskar exponentiellt mot antalet siffror (tror jag). Nu vet jag iofs inte hur stor noggrannhet just din kompilator vill att float och double vill ha , men det går nog att ta reda på med <float.h> FLT_DIG och DBL_DIG

Men läs Sodjans senaste inlägg igen, där finns faktiskt en del intressant information. (EDIT: Sodjan hann före med ett inlägg till - även det värt att begrunda)
Användarvisningsbild
sebgus
Inlägg: 408
Blev medlem: 11 december 2007, 09:51:17
Ort: Göteborg

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sebgus »

Ajjemen!

Lite lat är man väl av naturen.

Yes, talar om både om sinus/triangel, lite slarvigt kanske (och förvirrande). Just denna koden är till för sinusvågen.

Visste faktiskt inte om det där med lookup-tabeller och sånt, utan det var våran föreläsare (Lars Bengtsson, han som skrivit boken Mikrokontrollers - från assembler till RTOS) som rekommenderade oss att använda sinusfunktionen.

Men jag ska nog göra såhär: sova på saken och vakna upp imorn med fräsch skalle och försöka knäcka nöten.

Så länge kan ni få den ursprungliga koden. Kan tilläggas att denna tillsammans med en PIC18F458, 4MHz-kristall och ett RC-nät med en tidskonstant på 10ms fungerade alldeles ypperligt.

Kod: Markera allt

#include <pic18.h>
#include "math.h"

double x,y;

void main(){
		CMCON=0x07;
		TRISD=0xAA;
		TRISC=0x00;
		PR2=0xFF;
		CCP1CON=0x0C;
		TMR2ON=1;
		while(1){
				x=0;
				y=0;
				while(x<(2*3.14)){
				x = x+0.1;
				y=sin(x)+1;
				y = y*128;
				CCPR1L=(unsigned char)y;
				}
		}
}
Men godnatt på er allihopa! Återkommer säkert med fler frågor imorn.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sodjan »

Jo, ju sa ju att ungefär samma kod fungerade i en annan miljö, så
det finns ju ingen anledning att misstro just det. Å andra sidan så
betyder "fungerar" inte alltid att det är en bra eller rekomenderad lösning.

Jag tror att jag förstår vad du vill uppnå. Du ändrar puls/bredd
förhållandet enligt (t.ex) en sinusfunktion och genom att filtrera
utgången så filtreras grundtonen (d.v.s PWM-frekvensen) bort.

Problemet med din lösning är att det i princip inte finns någonting
som styr vilken frekvens (t.ex) sinussignalen får. Men det kanske
inte var viktigt ? Med en lookuptabell med en enkel SIN-kurva
så blir det enklare att styra sinus frekvensen eftersom det kommer
att åtgå betydligt mindre processortid i varje "varv" så att säga.
I ditt fall saknas timing helt och loopen kommer att gå med den
hastighet som (till stor del) sin() funktionen styr.

Men, visst, om uppgiften (?) bara var att generera en sinus
utan speciella krav på viss frekvens, så "fungerar" det kanske... :-)

Jag ser nu att det ena (fungerande) exemplet var med en PIC18 och
att du nu kör med en PIC16. Det är ju inte bara koden som är "ungefär"
samma, du har även bytt processor arkitektur vilket kan göra stor
skillnad, speciellt i hur funktioner som t.ex sin() är implementerade.
Det betyder sannolikt även att det är helt olika kompilatorer (och
matte libbar) vilket gör det hela ytterligare mer osäkert.
Användarvisningsbild
E85
Inlägg: 1274
Blev medlem: 29 maj 2007, 16:24:19
Ort: Övik

Re: Problem med PWM och triangel/sinusvåg

Inlägg av E85 »

OK, nu funkar den första filmen och det syns ju där nu att det inte
är fel på PWM-frekvensen så det kan du stryka. Jag kollade bara på
den andra filmen där filtret inte filtrerar tillräckligt.

Fast tycker fortfarande kurvan sveper för långsamt upp och ner.
Ska det bli nån slags triangelvåg att titta på måste ju frekvensen
på triangelvågen vara mycket högre.

Var har du koden för triangelvåg?
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Problem med PWM och triangel/sinusvåg

Inlägg av jesse »

Vad gör jag för fel? :)
Vad vill du ska hända?

Om det går på tok för långsamt så beror det just på det Sodjan säger - din sinusfunktion sin() tar så lång tid på sig att du inte kan köra snabbare. "lookuptabell" är inget konstigt - du beräknar ett antal sinusvärden i förväg ( t.ex 256 olika värden) och lägger dem i minnet (RAM eller EEPROM t.ex) , sedan läser du bara i tabellen när du ska ha ut svaret. Men då måste du överge "float" och börja arbeta med heltal. Då kommer det att gå så fort att du kan styra frekvensen med en delay-rutin, eller ännu hellre, ett interrupt från en timer. (Du kan t.o.m använda samma timer som du skapar PWM vågen med).
Användarvisningsbild
sebgus
Inlägg: 408
Blev medlem: 11 december 2007, 09:51:17
Ort: Göteborg

Re: Problem med PWM och triangel/sinusvåg

Inlägg av sebgus »

Yes! Nu gick det vägen här. Funkade efter lite trixande med en lookup-tabell. Tackar allihopa för tipsen om det, hade ingen aning. :)

Kör för närvarande med 16 värden på sinus, och uttnyttjar att den är symmetrisk så att jag får 64 värden.

Tänkte posta koden så ni kan tipsa om jag gjort något dumt i koden igen, kan vara bra att lära sig optimering och andra saker.

Kod: Markera allt

#include <pic16F887.h>

double Sinus(int b);

double y = 0;
int x = 0;


void main(){
	OSCCON = 0x75;
	PWM1CON = 0x07;
	TRISD = 0xFF;
	TRISC = 0x00;
	PR2 = 0xFF;
	CCP1CON = 0x0C;
	TMR2ON = 1;
	T2CKPS0 = 0;
	T2CKPS1 = 0;
	ADCON0 = 0xC1;

		while(1){
				while(x <= 16){
					y = 1.0+Sinus(x);
					CCPR1L = (unsigned char)(y*127);
					x++;
				}

				while(x >= 0){
					y = 1.0+Sinus(x);
					CCPR1L = (unsigned char)(y*127);
					x--;
				}

				while(x <= 16){
					y = 1.0-Sinus(x);
					CCPR1L = (unsigned char)(y*127);
					x++;
				}

				while(x >= 0){
					y = 1.0-Sinus(x);
					CCPR1L = (unsigned char)(y*127);
					x--;
				}
		}
}

double Sinus(int b){
	if (b == 0){
		return 0;
	}
	
	else
	if (b == 1){
		return 0.0980171403;
	}

	else
	if (b == 2){
		return 0.195090322;
	}

	else
	if (b == 3){
		return 0.2902846773;
	}
	
	else
	if (b == 4){
		return 0.3826834324;
	}

	else
	if (b == 5){
		return 0.4713967368;
	}
	
	else
	if (b == 6){
		return 0.555570233;
	}

	else
	if (b == 7){
		return 0.6343932842;
	}
	
	else
	if (b == 8){
		return 0.7071067812;
	}

	else
	if (b == 9){
		return 0.7730104534;
	}
	
	else
	if (b == 10){
		return 0.8314696123;
	}

	else
	if (b == 11){
		return 0.8819212643;
	}
	
	else
	if (b == 12){
		return 0.9238795325;
	}

	else
	if (b == 13){
		return 0.9569403357;
	}
	
	else
	if (b == 14){
		return 0.9807852804;
	}

	else
	if (b == 15){
		return 0.9951847267;
	}
	
	else
	if (b == 16){
		return 1;
	}
}
Bild:
Bild

Tack alla igen för tipsen!
Senast redigerad av sebgus 6 februari 2010, 13:19:50, redigerad totalt 1 gång.
Skriv svar