FAN RPM met Atmega PWM of CTC

Hierbij een andere vraag voor het creëren van een FAN/TACH signaal met behulp van een Atmega.

Ik heb het voor elkaar om voor 5 fans de rpm uit te lezen en via UART op mijn console te laten zien. Hartstikke leuk natuurlijk, maar nu wil ik om te beginnen dit signaal ook weer uitsturen over een out pin.

Nu dacht ik dit te doen met PWM, maar als ik alles goed begrepen heb gaat dit niet lukken, omdat mijn frequentie variable is ("traploos van 0 tot ..."). Wat ik tot zover begrepen heb is dat de dutycycle vrij te bepalen is, maar dat je bij de frequentie vast zit aan de prescalers die ook alleen op timer niveau te regelen zijn.

Bij CTC kan ik daarentegen precies vastzetten hoe lang het moet duren voor een puls moet komen.

Is dit correct? Of is het met PWM wel degelijk mogelijk?

Tevens heb ik met mijn 644 dan een probleem aangezien die maar 3 timers heeft, 2 8bit en 1 16bit.
Zijn hier oplossingen voor. Oftewel kan ik met 3 timers 5 fans aansturen (waarbij 1 timer gebruikt wordt voor het inkomende tach signaal)

Ja moet kunnen. In een ISR kun je die 5 PWM signalen wel maken.
Een kwestie van creatief programmeren.

Je kunt twee timers gebruiken.

Bijvoorbeeld, je gebruikt 1 timer voor de periode van het tacho signaal.
Die laat je iedere periode een INT genereren. Dat is het simpele stuk.

Nu komt het moeilijke stuk: Je kunt van te voren berekenen waar de PWM perioden van iedere fan precies moeten komen te liggen. De uitdaging is als er meerdere fans op dezelfde dutycycle uit komen.

Door in de periode ISR (die eerste) programmeer je nu de kortste periode voor de FAN die het eerst omgeschakeld moet worden in de tweede timer.
Op de ISR van die tweede timer zet je het signaal van de bijbehorende FAN om.
Daarna programmeer je de timer opnieuw met het restant van de tijd van de volgende FAN.

Uiteraard ga je die waarden niet in de ISR uitrekenen maar doe je dat van te voren in je main programma.

Dus stel de fans draaien op 100Hz -> 10mS periode, dat is je eerste timer
Stel je hebt 3 fans:

1 = 20% duty (dus 80% uit)
2 = 70% duty (dus 30% uit)
3 = 35% duty (dus 65% uit)

Dan zet je in een tabel de volgende waarden gesorteerd met de kortste periode vooraan (de tijden zijn cummulatief):

30,2 <---- pointer
35,3
15,1
0,0 <---- einde tabel.

In de periodic ISR reset je de pointer naar de tabel op de eerste waarde.
En start timer 2 op 3 mS (30% van 10mS), einde ISR.

In de tweede ISR zet je de pin aan (haal die op via de HUIDIGE) pointer hoog je de pointer op, controleer einde tabel (0) zo ja timer uit laten, zo nee nieuwe waarde in de timer zetten (35/10).

Nu geef ik even de waarden 30,35,15 op anders is het niet meer te volgen, maar de bedoeling is dat in die tabel de timer waardes van te voren uitgerekend zijn om de ISR zo kort mogelijk te maken.

Op die manier kun je net zoveel fans aansturen als je wilt.

Wel even opletten bij het herschrijven van de TABEL! Je moet alles uitrekenen op een andere locatie wegschrijven (twee table buffers dus). Dan met een global flag zorgen dat ISR naar de andere tabel kijkt (de periode timer). Anders gaat de ISR gek doen en krijg je onregelmatigheden in je PWM signaal.

Ik laat het hier even bij want er zullen nu al wel een aantal vragen hierover komen en wordt dit stuk text wel erg lang.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

henri, dank voor je beschrijving, zeker interessant. Maar ik denk goed te begrijpen uit je text dat je hiermee een FAN kan aansturen. Oftewel het PWM signaal NAAR de Fan.

Ik ben juist bezig het RPM/TACH signaal op te vangen met een atmega en die te bewerken (door een verhouding) en dan het aangepaste TECH signaal uit te sturen.

FAN -> 1:1 Tach 300 rpm -> ATmega -> 1:2 Tach 600 rpm -> Moederbord

Hiermee probeer ik het moederbord voor de gek te houden zodat deze een lagere pwm uitstuurt om de fan aan te sturen. Zodat in de nieuwe uiteindelijke situatie het er zo uit ziet:

FAN -> 1:1 Tach 150 rpm -> ATmega -> 1:2 Tach 300 rpm -> Moederbord

Wat resulteert in een lagere snelheid en dus minder geluid.
Ik weet dat dit wellicht omslachtig is, maar in mijn geval heb ik geen andere keus.

Misschien kan ik wel je idee gebruiken betreffende de tabellen. Het is me niet helemaal duidelijk, maar ik zou op het juiste punt een puls kunnen geven (eigenlijk een hele korte duty cycle).

Heb je wellicht een linkje betreffende die tabellen?
Momenteel schrijf ik de rpm van de 5 fans na berekening weg in een array.

Bijgevoegd de code waar ik momenteel mee werk:
Geef gerust tips, leer graag als het beter kan.

c code:


#ifndef F_CPU
#define F_CPU 20000000UL
#endif

# define USART_BAUDRATE 9600
# define BAUD_PRESCALE ((( F_CPU) / (16UL * USART_BAUDRATE) )  - 1)

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <stdint.h>                   // has to be added to use uint8_t
#include <stdlib.h>
#include <string.h> /* memset */

uint16_t rpmcount[5];                  // default start counting at 0 for fan 1
volatile uint8_t portbhistory = 0xFF;  // default is high because the pull-up
volatile unsigned long timer1_millis;  // long milliseconds_since;

ISR (PCINT0_vect)
{
	uint8_t changedbits;

	changedbits = PINA ^ portbhistory;
	portbhistory = PINA;

	if(changedbits & (1 << PA0))
	{
		/* PCINT0 changed */
		rpmcount[0]++;
	}

	if(changedbits & (1 << PA1))
	{
		/* PCINT1 changed */
		rpmcount[1]++;
	}

	if(changedbits & (1 << PA2))
	{
		/* PCINT2 changed */
		rpmcount[2]++;
	}
	if(changedbits & (1 << PA3))
	{
		/* PCINT3 changed */
		rpmcount[3]++;
	}
	if(changedbits & (1 << PA4))
	{
		/* PCINT4 changed */
		rpmcount[4]++;
	}
}

void USART_Init( unsigned int baud )
{
	/* Set baud rate */
	UBRR0H = (unsigned char)(baud>>8);
	UBRR0L = (unsigned char)baud;
	/* Enable receiver and transmitter */
	UCSR0B = (1<<RXEN0)|(1<<TXEN0);
	/* Set frame format: 8data, 1stop bit */
	UCSR0C = (3<<UCSZ00);
}

void INPUT_Init()
{
	DDRA &= ~((1 << DDA0) | (1 << DDA1) | (1 << DDA2) | (1 << DDA3) | (1 << DDA4)); // Clear the PB0, PB1, PB2 pin
	 
	PORTA |= ((1 << PA0) | (1 << PA1) | (1 << PA2) | (1 << PA3) | (1 << PA4));      // turn On the Pull-up
	
	PCICR |= (1 << PCIE0);     // set PCIE0 to enable PCMSK0 scan
	PCMSK0 |= (1 << PCINT0);   // set PCINT0 to trigger an interrupt on state change
}

void OUTPUT_Init()
{
	DDRD |= (1<<DDD3);          // set LED pin PD1 to output
}

// This function is used to read the available data from USART. 
// This function will wait until data is available.
unsigned char USART_Receive( void ) // Extracted function from the datasheet
{
	/* Wait for data to be received */
	while ( !(UCSR0A & (1<<RXC0)) )
	;
	/* Get and return received data from buffer */
	return UDR0;
}

// This function writes the given "data" to the USART which then transmit it via TX line
void USART_Transmit(  char string[] ) // Extracted function from the datasheet
{	
	int i=0;

	//define the string to be transmitted
	//char string[] = "MoMos lOveRs";

	while(string[i] != 0x00)
	{
		//transmit the string by putting characters into UDR one by one
		UDR0 = string[i++];

		//wait until UDR is empty to take new byte
		while(!(UCSR0A & (1<<UDRE0)));
	}	
}

ISR (TIMER1_COMPA_vect)
{
	timer1_millis++;
}

unsigned long millis ()
{
	unsigned long millis_return;
	
	// Ensure this cannot be disrupted
	ATOMIC_BLOCK(ATOMIC_FORCEON) {
		millis_return = timer1_millis;
	}
	
	return millis_return;
}

int main(void)
{
	INPUT_Init();                          // Init Input ports
	USART_Init(BAUD_PRESCALE);             // Init UART functionality
	OUTPUT_Init();                         // Init output ports
	
	TCCR1B |= (1 << WGM12);                // configure timer1 for CTC mode
	TIMSK1 |= (1 << OCIE1A);               // enable the CTC interrupt

	OCR1A = 0.001 * F_CPU/1 - 1;           // set the CTC compare value - 19531;
	
	sei();                                 // turn on interrupts
	/* 
	20000000 Hz / 1024 =19531.25 Hz. Counting to 65535 at this speed would take	65535 / 19431.25 = 3.355392 seconds.
	Therefore 1 second will take 65535 / 3.355392 = 19531.25 increments. To set this as the maximum the timer should count to, 
	we set Output Compare Register 1 A (OCR1A) to 19531.
	*/
		
	TCCR1B |= (1 << CS10);                 //| (1 << CS12)); // start the timer at 20MHz/1024
	
	// read RPM and calculate average every ten readings.
	const long numreadings = 10;
	uint16_t readings[5][numreadings];
	uint16_t RPM_Average[5];
	uint8_t index = 0;
	uint32_t total[5];
	unsigned long lastmillis = 0;
	DDRD |= (1<<DDD3);          // set LED pin PD1 to output
	char c[10];
	
	// Reset array "total"
	memset(total, 0, sizeof total);
	
	// Reset array "readings"
	memset(readings, 0, sizeof readings);
	
	// Reset array "rpmcount"
	memset(rpmcount, 0, sizeof rpmcount);
	
	while (1) {
		if (millis() - lastmillis >= 1000){  /* Update every one second, this will be equal to reading frequency (Hz).*/
			
			//Disable interrupt when calculating
			cli();
						
			// Calculate current RPM
			for (int y=0; y<=4; y++){
				readings[y][index] = (rpmcount[y] * 60);
			}
			
			// Raise index of array with 1
			index++;

			// If array size holds 10 elements run the average calculator
			if (index==10){
				// Do complete calculation		
				
				// Reset array "total"
				memset(total, 0, sizeof total);
				
				//ltoa(total[4], c, 10);
				//USART_Transmit(c);
				//USART_Transmit("\n\r");
				
				// Calculate total RPM for 10 items
				for (int y=0; y<=4; y++){	
					for (int x=0; x<=9; x++){
						total[y] = total[y] + readings[y][x];
					}

					 //Calculate average RPM based on former total
					RPM_Average[y] = total[y] / numreadings;	
					
					// Report to UART
					USART_Transmit("RPM average FAN ");
					itoa(y+1, c, 10);
					USART_Transmit(c);
					USART_Transmit(" : ");
					ltoa(RPM_Average[y], c, 10);
					USART_Transmit(c);
					USART_Transmit("\n\r");		
				}
				
				// Reset index counter for array
				index=0;

				// Reset array "readings"
				memset(readings, 0, sizeof readings);
				
				// Reset array "rpmcount"
				memset(rpmcount, 0, sizeof rpmcount);
				
				// Update lastmillis
				lastmillis = millis(); 
				PORTD ^= (1 << PD3);
			}
			
			//enable interrupt
			sei();	
		}
	}
}

Goh, ik heb precies hetzelfde ooit willen maken voor een server met een bak fans erin die meer stroom vreten als de hele machine zelf! (helaas tijdgebrek...)

Ik begrijp precies wat je wilt. Dat is inderdaad andersom als wat ik beschreven heb richting het MOBO.

Om je fans aan te sturen vanaf je MOBO kun je dat wel gebruiken om de duty mooi te regelen.

Andersom moet je truuken uit gaan halen. Kijk een op het internet naar implementaties van een DDS, hierbij kun je een willekeurige frequentie maken uit een hoge frequentie (lees timer) door fase accumulatie.

Wat je eigenlijk doet is simpel uitgelegd: in de timer ISR tel je elke keer een counter op bij een vorige waarde (accumulator) en die gebruik je weer in een modulo deling om je output bit te maken. Op die manier kun je "breuken" maken op een vrij efficiente manier.
Door meerdere van die "accumulatoren" te maken maak je alle frequenties.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Henri, heb momenteel 2 stukken sample code gevonden om me in de goede richting te helpen.
Eerst ga ik proberen 1 fan aan te sturen (met een vaste frequentie). Hierna frequentie veranderen via UART en daarna de interactie met bovenstaande code.

Voorbeelden die ik heb gevonden:
http://www.scienceprog.com/avr-dds-signal-generator-v20/
http://www.instructables.com/id/Arduino-Waveform-Generator/?ALLSTEPS

Wat ik me wel afvroeg (naar aanleiding van de eerste link) is de wavefrom die ik moet hebben. Dit zou toch een square signal moeten zijn dan?

Overigens moet ik tot ongeveer 340Hz kunnen genereren. Dit zou overeenkomen met 20000rpm (wat al hoog is).

Heb nog geen goede uitwerking gevonden die me op weg kan helpen.
Wel even zitten denken waarom het niet opgelost kan worden door in de timer interrupt 5 "subtimers" te zetten die allemaal naar een eigen waarde tellen tijdens. In als actie dan een switch op de output.

In principe is tach een pulse en zoek ik een pulsegenerator.
Wat ik lees op deze site lijkt te doen wat u aangeeft:
http://www.instructables.com/id/Atmel-Xmega-USBSerial-Arbitrary-Wavefo…

Echter kan ik momenteel de C source niet downloaden.
Wat denk u/jullie

[Bericht gewijzigd door Henry S. op zondag 22 maart 2015 15:39:03 (30%)

Op 20 maart 2015 07:25:48 schreef Sebastiaan06:
Wat ik me wel afvroeg (naar aanleiding van de eerste link) is de wavefrom die ik moet hebben. Dit zou toch een square signal moeten zijn dan?

Ja moet een square zijn. Daarom zei ik al dat je wat creatief moet programmeren, een DDS wordt gebruikt voor een sinus waveform maar het principe beginsel is ook bruikbaar om een blok te maken.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Oke, dan ga ik toch weer verder zoeken naar een dds.
Bij en sqaure heb ik dan die weerstanden en extra outputs dus niet nodig. Dus als ik dat aanpas zou ik een eind in de goede richting moeten komen.

Moet eerst overigens nog een voorbeeld vinden.

Oke, na veel zoeken en lezen kom ik eigenlijk sturctureel een oplossing tegen waarbij in de timer interupt een counter(accumulator) word gebruikt met IF statements. Aangezien de meeste DDS maar 1 frequentie hoeven te maken zie je in de interupt dus ook maar 1 accumulator.

In mijn geval zou ik dus 5 accumulators toepassen in de timer interupt. In onderstaande code (die ik op basis van een arduino voorbeeld heb aangepast) heb ik 1 accumulator gemaakt op basis van "t". Deze kan ik natuurlijk uitbreiden met "q", "x", "y" en "z":

Toch ben ik wel nieuwschierig naar uw opmerking betreffende modulo deling. Enige wat ik me hierbij kan voorstellen is als volgt:
1 accumulator -> "test"
door "test" te delen door modulo "period" komt een getal, alleen bij een heel getal is een periode voorbij en kan er een pulse gegeven worden.
Hierbij moet je dan wel kunnen detecteren dat het een heel getal is.
Zelf heb ik in mijn opleiding nooit echt veel met mod gedaan en alles wat ik heb gedaan is heel lang geleden. Internet kon me niet direct in de goede richting sturen dus wellicht kan u me het verduidelijken.

Verder kan ik dus de 5 fan accumulatoren gebruiken in de timer, maar ook een accumulator toevoegen om elke 1000ms een update van de frequency te doen, zodat deze ook niet meer in de main loop wordt uitgevoerd en als ik alles goed begrepen heb efficienter zou zijn.

alle feedback is welkom.

[code=C]
#ifndef F_CPU
#define F_CPU 20000000UL
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <stdlib.h>

//variables for PW pot monitoring
float pulseWidth;
int pulseWidthScaled;
int PWCurrent;
uint8_t PWTolerance = 8; //adjust this to increase/decrease stability of PW measurement

//variables for freq pot monitoring
int frequency;
int freqCurrent;
uint8_t freqTolerance = 2; //adjust this to increase/decrease stability of frequency measurement
unsigned int freqscaled;

long t;
long samplerate;
long period;

uint16_t Average_RPM = 10000; // Default RPM to start with
uint16_t Average_PW = 10; // Pulsewidth

void init_Timer() {
//TIMER INTERRUPT SETUP
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B

// set compare match register- 100khz to start
OCR1A = 199; // = (20 000 000 / 100 000) - 1 = 159
TCCR1B |= (1 << WGM12); // turn on CTC mode
TCCR1B |= (1 << CS10); // Set CS10 bit for 0 pre-scaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
}

void init_Main(){
samplerate = 100000; // 100khz

//initialize variables
frequency = Average_RPM / 60 ; // initialize frequency from fan
period = samplerate/frequency; // Calculate 1 period versus complete samplerate
pulseWidth = Average_PW;
pulseWidthScaled = Average_PW*period; // Calculate length of pulse during period
}

void init_Ports(){
//set port/pin mode
DDRD |= (1<<DDD3); // set LED pin PD1 to output
}

void checkFreq() { // Function to be triggered if frequency needs to be adjusted during runtime
freqCurrent = Average_RPM / 60 ; // FAN RPM
if (abs(freqCurrent-frequency)>freqTolerance){ // if new value exceeds tolerance
frequency = freqCurrent; // new frequency
period = samplerate/frequency; // Calculate 1 period versus complete samplerate
pulseWidthScaled = Average_PW*period; // Calculate length of pulse during period
}
}

void checkPW() { // Function to be triggered if pulse width needs to be adjusted during runtime
PWCurrent = Average_PW;
if (abs(PWCurrent-pulseWidth)>PWTolerance){ // if new value exceeds tolerance
pulseWidth = PWCurrent; // new pulse width
pulseWidthScaled = Average_PW*period; // Calculate length of pulse during period
}
}

ISR(TIMER1_COMPA_vect){ // timer 1 interrupt
// increment t and reset each time it reaches period
t++;
if (t >= period){
t = 0;
}

if (pulseWidthScaled <= t && (!PD3)) { // Tijdelijk een loop voor pulse width en period, ligt eraan
PORTD |= (1<<PD3); // of een (enkele) pulse wordt gedetecteerd door het mobo
} // In dat geval is alleen de period voldoende en bij de start van de period
else if (PD3 && t > pulseWidthScaled){ // een pulse.
PORTD &= ~(1<<PD3);
}
}

int main(void)
{
cli(); // disable interrupts
init_Timer(); // initialize timer
init_Main(); // initialize startup variables
init_Ports(); // initialize ports
sei(); // enable interrupts
while (1) {
}
}
[/code]

Op 27 maart 2015 11:09:22 schreef Sebastiaan06:
Voor een ander AVR project heb ik 2 kleine schematjes gemaakt voor de detectie en creatie van een TACH signaal.
Het avr programma is bijna af, en de detectie doe ik nu met een oude Transistor.

Ik heb bijgevoegd het circuit wat ik in gedachte heb.
Wat ik me afvroeg is of ik niet een transistor (bc847) zou kunnen gebruiken ipv de IRF520.
En daaropvolgend of de weerstand in de lijn richting Moederbord afdoende is (en niet bijvoorbeeld zwaarder moet zijn. (Heb geen idee of een moederbord detectie afhankelijk is van stroom of spanning?)

Graag jullie advies.

Ps Frequentie is maximaal 200Hz

Zijn cpu fan tacho signalen geen open collectoruitgangen?

[Bericht gewijzigd door Henry S. op maandag 30 maart 2015 19:28:35 (1%)

LDmicro user.

Dat zijn ze inderdaad. Dus noch het linkerschema noch het rechterschema gaan werken.

Om het tacho-signaal in te lezen in je AVR kan je volstaan met een input-pin met een pullup (pullup-weerstand activeren in de AVR). Best ter bescherming een serieweerstand van bv. 2K2 zetten tussen de AVR-pin en de ingang.

Om een tacho-signaal naar je moederbord te sturen gebruik je het BC847 schema. De AVR-uitgang aan de weerstand van 10K. De collector van de transistor aan het moederbord. Ook hier kan je tussen collector en moederbord een serieweerstand zetten (470 ohm ofzo) ter beveiliging.

MGP, helemaal gelijk. Op de een of andere manier heb ik wel rpm gemeten met de AVR... Geen idee hoe dat kan. Had dit van een site gevonden. Geheel wordt er wel goedkoper door :)

subsonik, u bent me voor. Ben net het schema aan het aanpassen. Toch dank voor uw adviezen, zal ze zo meteen verwerken.

Attached de nieuwe versie. Ga vanavond meteen even de input testen.

Niet helemaal juist ;)

De rechtse kant van R1 moet aan de + liggen van de AVR voeding (5V?).
De linkse kant aan de inputpin EN de tacho_sens.

R4 moet weg, ik zeg niet dat het niet zal werken maar in de uitgang van van de fansensor zit ook geen weerstand.

LDmicro user.

Op 27 maart 2015 15:16:38 schreef MGP:
De rechtse kant van R1 moet aan de + liggen van de AVR voeding (5V?).
De linkse kant aan de inputpin EN de tacho_sens.

de functie van de R die u beschrijft is de interne AVR pullup?
(die heb ik hier juist niet getekent en de R1 is om de stroom te beperken)

R4 moet weg, ik zeg niet dat het niet zal werken maar in de uitgang van van de fansensor zit ook geen weerstand.

Dus je sluit de TACH_SENS|Mainboard met gnd (uiteraard op moment dat output pin HIGH is)?

Ja dat moet een pullup zijn.
De stroom beperken van een ingang heeft weinig zin, µA grootorde.

Op 27 maart 2015 15:39:01 schreef Sebastiaan06:

Dus je sluit de TACH_SENS|Mainboard met gnd (uiteraard op moment dat output pin HIGH is)?

Ja, origineel is dat ook zo.

LDmicro user.
Arco

Special Member

De interne pull-ups (<100uA) zijn veel te zwak voor betrouwbaar resultaat...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 27 maart 2015 15:51:25 schreef Arco:
De interne pull-ups (<100uA) zijn veel te zwak voor betrouwbaar resultaat...

U & MGP raden dus aan om voor deze applicatie van een aparte pullup gebruik te maken. Om deze reden heb ik deze nu weer toegevoegd.

Op 27 maart 2015 15:49:41 schreef MGP:
De stroom beperken van een ingang heeft weinig zin, µA grootorde.

Heb het aangepast. Dank u.

Dat is beter, naar mijn gevoel toch ;)

LDmicro user.

Op 27 maart 2015 15:49:41 schreef MGP:
De stroom beperken van een ingang heeft weinig zin, µA grootorde.

De +12V en tacho pinnen zitten vlak naast elkaar op de fanconnector. Een ongelukje waarbij +12 op de tacho terecht komt is snel gebeurd! (een fan 1 pin verschoven proberen inpluggen is al voldoende)

De stroom beperken op een ingang heeft dan ineens wél zin tenzij je graag rookbommen maakt :-) Dus serieweerstandje tussen tacho en AVR input. Best de pullup VOOR de serieweerstand zetten (kant tacho pin).

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Henri, klopt. Ben nog met de code bezig. Hoofdlijnen zijn klaar alleen heb ik wat timer problemen.

MGP, subsonic, afgelopen weekend getest met exact het voorgestelde meetcircuit (alleen de rpm van de fan). Werkte niet....

Dus op internet gezocht en kwam tegen dat voor veel fans de tach betrouwbaar werkt als deze wordt gevoed met 12V. Daarna verder gezocht hoe ik dit kon bereiken. Had wel iets van resistor devider gehoord, maar heb daar geen ervaring mee.

Kwam uiteindelijk deze link tegen:
http://www.pavouk.org/hw/fan/en_fan4wire.html

Hierbij zit er ook een R naar ground om de AVR geen 12V te geven.
De detectie werkt nu weer.

Om nog even op de opmerking van subsonic terug te komen betreffende de R richting te fan om foute aansluiting te voorkomen.
Waarom geen diode?

rbeckers

Overleden

"resistor" is weerstand en "devider" is deler.
Dus een weerstandsdeler. ;)
Om stroom te beperken gebruik je een weerstand en geen diode.

Op 30 maart 2015 07:28:12 schreef Sebastiaan06:
Werkte niet....

GND's van beide schakelingen vergeten door te verbinden?

Je moet er ook eens de gewoonte van maken om alles uit te meten, als je iets wilt veranderen waarvan je geen schema hebt.

Er zijn ook veel fan's zonder temperatuurregeling ingebouwd.

Ik zie het verschil niet met uw schakeling, enkel wat weerstanden die erbij gekomen zijn om die 12V niet op de controller te krijgen.

Nu, als het werkt is het ok.

Ik vraag mij af welk signaal jij met uw controller opwekt?

LDmicro user.

MGP, met werkte niet bedoelde ik om met 5V te meten.
Excuus als ik niet duidelijk was hierin. Als ik 12V gebruik dan werkte het wel. Het klopt betreffende de weerstanden om die niet op de controller te krijgen.

Mijn post was meer als aanvulling op uw schema. Voor de rest is er niks veranderd.

Op 30 maart 2015 08:42:50 schreef rbeckers:
"resistor" is weerstand en "devider" is deler.
Dus een weerstandsdeler. ;)
Om stroom te beperken gebruik je een weerstand en geen diode.

Dat begrijp ik, maar in dit geval ging het niet om de stroom van de 12V richting te FAN, maar indien je fout aansluit van de FAN richting te controller (de andere kant op, althans zo begreep ik de opmerking van subsonik)

Op 30 maart 2015 08:55:48 schreef MGP:
[...]
Ik vraag mij af welk signaal jij met uw controller opwekt?

Wat bedoeld u?

[Bericht gewijzigd door Sebastiaan06 op maandag 30 maart 2015 09:03:34 (11%)

Ik vermoed dat je via uw controller het signaal afkomstig van de fan wilt opdrijven om zo een lager toerental van de fan te verkrijgen.

Ik lees dat zo'n signaal rond de 21Khz is, dat je moet inlezen en dat jij een, laat ons zeggen, 25Khz van maakt, met toch een bepaalde pulsbreedte.
Heb je dat allemaal opgemeten?

LDmicro user.

Ah, ik snap uw vraag. Helaas heb ik geen scope, dus kan het zelf niet meten.
Heb via google 2 dingen gevonden. Waarbij ik nog moet testen wat waarheid is en wat werkt.

Het ene is dat een gewone blokwave zou moeten werken en het andere is een 22,5% pulsebreedte. Maar daar ben ik nog mee bezig. IK heb eerst nog een timer probleem wat ik moet oplossen en daarna kan ik eerst de 1:1 doorzetten doen, alvorens ik ga schalen.
Waarschijnlijk een factor 1:3. Dus inderdaad nu 600Hz en ik vertaal naar de pc 1800hz, pwm zal door de MB worden aangepast om toch de 600 te verkrijgen waardoor de fan 200 zal gaan draaien.
(Althans dat is de bedoeling)

[Bericht gewijzigd door Henry S. op maandag 30 maart 2015 19:21:37 (24%)