Pagina 4 van 4

Re: Adruino Perikelen

Geplaatst: 31 aug 2016, 17:04
door -----

Re: Adruino Perikelen

Geplaatst: 31 aug 2016, 23:11
door PA4MW
Meteen leer ik weer wat bij, thanks :mrgreen: ! Inderdaad stuur ik de transistor aan via analogwrite() zoals PA3CQN schreef. Ik zal trouwens de code even meesturen Lodewijk, zie hieronder. Zou ik nog wat kunnen optimaliseren?

Uiteindelijk is het gelukt het aantal RPM uit te lezen met een extra PNP transistor! :lol: Het probleem zat hem in de 'floating ground'. Hierdoor ging er via de Arduino een stroompje lopen en werd de processor warm. En toch, zelfs die mishandelpoging heeft ie overleefd; ze zijn nog best fool proof die dingen! Heb er even een schema van getekend (let niet op mijn MS paint skills :wink: ):

Afbeelding

Ik heb de elco tussen pen 6 en GND weggehaald; in dit nieuwe circuit werkt PWM niet goed meer met een elco, het is dan meer aan of uit.

Verder heb ik een waarschuwingsledje toegevoegd; wanneer de temperatuur boven de 55 graden komt gaat ie branden. En heb een pull up weerstandje toegevoegd tussen 5V en de PWM pen zoals PA3CQN schreef. Zonder werkt het ook, maar niet voor lang; na verloop van tijd wordt de waarde dan niet meer uitgelezen. Kan je dit ook niet softwarematig doen met INPUT_PULLUP?

Nu mét RPM:
Afbeelding

En nu twee transistoren! Ik denk dat ze het zonder koelblokje ook wel overleven; ze worden ongeveer lauw warm. Vooral de elco weghalen scheelde inderdaad!

Afbeelding

En de code:

Code: Selecteer alles


/*-----( Library's )-----*/
#include <U8glib.h>
#include <OneWire.h>
#include <Wire.h>
#include <DallasTemperature.h>
/*-----( Library's )-----*/
 
U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);       // Constructor For Connection SPI Nokia 5110 Display: CLK = 13, DIN = 11, CE = 10, DC = 9, RST = 8

int fan = 6;            // the pin where fan is
int led = 7;            // led pin
int tempMin = 35;   // the temperature to start the fan
int tempMax = 55;  // the maximum temperature when fan is at 100%
int fanSpeed;      
int fanLCD;
int ticks = 0, Speed = 0;
int hallsensor = 2; 

typedef struct{   
char fanntype;
unsigned int fanndiv; }

fannspec;

//Definitions of the fans
//This is the varible used to select the fan and it's divider,
//set 1 for unipole hall effect sensor
//and 2 for bipole hall effect sensor

fannspec fannspace[3]={{0,1},{1,2},{2,8}}; char fann = 1;

#define VT_PIN A0                           // connect VT
#define AT_PIN A1                           // connect AT
#define ONE_WIRE_BUS 4                 // Data wire is plugged into pin 4 on the Arduino
#define T_PRECISION 12                   // Set variable T_PRECISION to 12 (12 bit resolution on the 18D20)

OneWire oneWire(ONE_WIRE_BUS);            // Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire);        // Pass our oneWire reference to Dallas Temperature. 

// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
 
DeviceAddress insideThermometer = { 0x28, 0xFF, 0xFC, 0x7F, 0xC1, 0x15, 0x01, 0x48 };

void pickrpm ()
//This is the function that the interupt calls
{ ticks++; }

void setup(void)
{
  sensors.begin();    // Start up the library
  sensors.setResolution(insideThermometer, T_PRECISION);    // Resolution
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(hallsensor, INPUT); 
  attachInterrupt(0, pickrpm, RISING); 
  digitalWrite(hallsensor, HIGH);
}
 
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00) {
u8g.print("ERROR");
} 
else {
u8g.print(tempC);
}

if(tempC < tempMin) {   // if temp is lower than minimum temp
fanSpeed = 0;               // fan is not spinning
digitalWrite(fan, LOW);       
} 
  
if((tempC >= tempMin) && (tempC <= tempMax)) {       // if temperature is higher than minimum temp
fanSpeed = map(tempC, tempMin, tempMax, 58, 255);    // the actual speed of fan
fanLCD = map(tempC, tempMin, tempMax, 0, 100);        // speed of fan to display on LCD
analogWrite(fan, fanSpeed);                                        // spin the fan at the fanSpeed speed
} 
   
if(tempC > tempMax) {                           // if temp is higher than tempMax
digitalWrite(led, HIGH);                           // turn on led 
} 
else {                                                  // else turn of led
digitalWrite(led, LOW); 
}
}
 
void loop(void)
{
int vt_read = analogRead(VT_PIN);
int at_read = analogRead(AT_PIN);
float voltage = vt_read * (5.0 / 1023.0) * 11;
float current = at_read * (5.0 / 1023.0);
float watts = voltage * current;

ticks = 0;      // Make ticks zero before starting interrupts.

interrupts();    // or use sei(); to Enables interrupts
delay (1000);     //Wait 1 second
noInterrupts();  //  or use  cli();  to Disable interrupts

//Times sensorclicks (which is apprioxiamately the fequency the fan 
//is spinning at) by 60 seconds before dividing by the fan's divider
// this gives reasonable accuracy in upto few 10s of RPM
// for more accurate and fast measurements, other algorithms is required.
Speed = ((ticks * 60)/fannspace[fann].fanndiv);  

u8g.setContrast(130); 
sensors.requestTemperatures();     // Ask temp

u8g.firstPage();  
    do {
    u8g.setFont(u8g_font_6x12);                      
    u8g.drawStr(0, 7, "Ubuf");           
    u8g.setPrintPos(27, 7);                      
    u8g.print(voltage);                            
    u8g.setPrintPos(61, 7);  
    u8g.print("Volt");

    u8g.setFont(u8g_font_6x12);                      
    u8g.drawStr(0, 15, "Ibuf");           
    u8g.setPrintPos(27, 15);                      
    u8g.print(current);                            
    u8g.setPrintPos(61, 15);  
    u8g.print("Amp");

    u8g.setFont(u8g_font_6x12);                      
    u8g.drawStr(0, 23, "Pbuf");           
    u8g.setPrintPos(27, 23);                      
    u8g.print(watts);                            
    u8g.setPrintPos(61, 23);  
    u8g.print("Watt");

    u8g.setFont(u8g_font_6x12);                      
    u8g.drawStr(0, 31, "Fan");           
    u8g.setPrintPos(19, 31);                      
    u8g.print(fanLCD);                            
    u8g.setPrintPos(31, 31);  
    u8g.print("%");
    char  SpeedString[4];    // Buffer to store string of 4 chars + 0 termination
    sprintf(SpeedString, "%4d", Speed);   // change this to %3, 4 ,5 etc depending upon your max speed
    u8g.setPrintPos(39, 31);  
    u8g.print(SpeedString);
    u8g.setPrintPos(67, 31);  
    u8g.print("RPM");
    
    u8g.setFont(u8g_font_6x12);                      
    u8g.drawStr(0, 39, "Temp");           
    u8g.setPrintPos(27, 39);                      
    printTemperature(insideThermometer);                            
    u8g.setPrintPos(61, 40);  
    u8g.print("\260C");
 }  
 
 while( u8g.nextPage() ); 
    delay(100);
}
 

Re: Adruino Perikelen

Geplaatst: 01 sep 2016, 10:56
door PA3CQN
Eigenlijk zou het ook niet moeten werken .... althans theoretisch.
Ik zou het zo willen verklaren:

Een PC fan is een borstelloze motor met een ingebouwde hall-sensor/motorsturing die de twee groepen spoelen schakelt.
De snelheidsuitgang is eigenlijk gewoon de uitgang van die hall-sensor.
Een drie-draads fan zou je eigenlijk lineair moeten sturen, dus op basis van spanning. Dat is wat je in eerste instantie deed,
Arduino PWM afgevlakt met elco.

Lineaire sturing heeft als nadeel dat de motor niet lekker loopt bij lage spanning. En dat je vermogen verstookt in de transistor.
Ook werkt de RPM uitgang niet zoals je verwacht: als je de fan op halve spanning laat draaien in je oorspronkelijke schakeling zal de RPM uitgang
wisselen tussen V+ en V+/2. En dus niet naar GND schakelen.

Een fan met echte pwm sturing heeft 4 draden: voeding, rpm signaal en een pwm stuursignaal ( iets van 25 kHz ).

Maar er is nog een manier: schakel een driedraads fan steeds aan en uit, maar op een lage frekwentie. En dat is wat hier gebeurd.
De PWM frekwentie van de Arduino is laag, 490 Hz. Zo laag dat het lijkt alsof je de fan aan en uit zet. Door de traagheid draait ie nog even
door in de periode dat ie uit is. Maar 490 Hz is wel weer zo hoog dat je niet merkt dat de fan steeds in snelheid varieert.

Als de motor uit ( spanningsloos ) is werkt ook de hall-sensor niet meer. Dus in de periode zonder spanning komt er geen puls uit.
En dan komt die weerstand in beeld: die levert genoeg om de hall-sensor te laten werken.

Ideaal is het niet, maar als het werkt is het ook goed.

Re: Adruino Perikelen

Geplaatst: 01 sep 2016, 12:00
door PA4MW
Dank voor je uitleg CQN! :) Zo had ik het ook begrepen inderdaad. Ik had voor de gein geexperimenteerd zonder pull up weerstand en dan viel inderdaad het aantal RPM na verloop van tijd terug naar 0, waarschijnlijk omdat de hall sensor niet meer actief is. Daarnaast maakt de delay van 1 seconde de kans nog kleiner dat je net meet op het moment dat de hall sensor niet actief zou zijn dan wanneer je continue meet. Op CO postte iemand trouwens een leuk document met een overzicht hoe je fans kunt 'temmen' http://www.analog.com/library/analogdia ... _speed.pdf

Re: Adruino Perikelen

Geplaatst: 31 mei 2017, 18:59
door Dopp
Hallo Allemaal,


Leuk arduino CTCSS projectje!

4 ledjes en een button etc.


Als ledje 13 op arduino uno brand dan standaard 193 Hz

Anders 71, 77, 82 or 88 Hz..

Button laat je cycle door de CTCSS tonen

en ledje geeft welke toon actief is

Zie Sketch(CTCSS-PA3BNX) en foto en circuit lowpas met potmeter


Have fun ....

CTCSS.ino

Code: Selecteer alles

/*
 *((C))PA3BNX CTCSS Encoder for my TM421 es
 * @31-05-2017
 * led13 is default 293 Hz
 
 */
const byte pinCTCSS=2; //Audio
const byte pinButton=3; //Button
const byte pinLed1=4;
const byte pinLed2=5;
const byte pinLed3=6;
const byte pinLed4=7;
const byte pinLed13=13;


//Tone Hz values
const int T0=0;
const int T1=193; //PI2NOS 
const int T2=72;
const int T3=77;
const int T4=83;
const int T5=89;

//Integer
int x;

void CheckLeds()
{
 int i=75;
 digitalWrite(pinLed1,HIGH);
 delay(i);
 digitalWrite(pinLed2,HIGH);
 delay(i);
 digitalWrite(pinLed3,HIGH);
 delay(i);
 digitalWrite(pinLed4,HIGH);
 delay(i);
 digitalWrite(pinLed13,HIGH);
 delay(1000); 
 digitalWrite(pinLed1,LOW);
 digitalWrite(pinLed2,LOW);
 digitalWrite(pinLed3,LOW);
 digitalWrite(pinLed4,LOW);
 digitalWrite(pinLed13,LOW);
}

void SetTone(int t)
{
 noTone(pinCTCSS);
 digitalWrite(pinLed13,LOW);
 digitalWrite(pinLed1,LOW);
 digitalWrite(pinLed2,LOW);
 digitalWrite(pinLed3,LOW);
 digitalWrite(pinLed4,LOW);
 if (t!=0){tone(pinCTCSS,t);}
 
 }//Last SetTone


void setup() {
  // put your setup code here, to run once:
//Serial.begin(9600);

//Input
pinMode(pinButton,INPUT_PULLUP);
//Led Output
pinMode(pinLed1,OUTPUT);
pinMode(pinLed2,OUTPUT);
pinMode(pinLed3,OUTPUT);
pinMode(pinLed4,OUTPUT);
pinMode(pinLed13,OUTPUT);

//Check Leds
CheckLeds();

//Default tone setup
x=-0;
SetTone(T1);
digitalWrite(pinLed13,HIGH);
}

void loop() {
  // put your main code here, to run repeatedly:

//Read the Push Button

while (digitalRead(pinButton)==HIGH) 
{
  delay(150);//Debounce hi
  //Do nothing
}  


x++;
if (x > 4) {x=-1;}

//Serial.print(x);

switch(x)
{
case -1:
 SetTone(T0);
 break;
case 0:
 SetTone(T1);
 digitalWrite(pinLed13,HIGH);
 break;
case 1:
 SetTone(T2);
 digitalWrite(pinLed1,HIGH);
 break;
case 2:
 SetTone(T3);
 digitalWrite(pinLed2,HIGH);
 break;
case 3:
 SetTone(T4);
 digitalWrite(pinLed3,HIGH);
 break;
case 4:
  SetTone(T5);
  digitalWrite(pinLed4,HIGH); 
  break;
default:
  //Nothing ?
   break;
}
 
 delay(500); //Delay for next CTCSS 

}//Last Bracket Loop


Re: Adruino Perikelen

Geplaatst: 31 mei 2017, 21:19
door PE1CID
Dag Lodewijk,

Ik zie in je code dat je voor de toon zelf de instructie 'tone' gebruikt. Deze instructie genereert een blokgolf en een CTCSS toon vereist een sinus. Bij een blokgolf worden ook de derde en vijfde harmonischen van de toon gegenereert en die vallen bij lagere tonen in het bereik van de andere CTCSS tonen en bij de hogere CTCSS tonen in het audio bereik.

Een betere methode voor het genereren van CTCSS tonen met een Arduino is het gebruik van een PWM signaal. Je laat de duty cycle van het PWM signaal sinus vormig varieren en hoeft dan alleen maar de sample frequentie uit te filteren.

Ik heb een CTCSS generator op basis van een Arduino gemaakt. De sample frequentie is ongeveer 32 kHz dat heel gemakkelijk uitgefiltert kan worden ten opzichte van de CTCSS tonen met maximaal 250 Hz. De output van het filter geeft een schone sinus.

Als je geintereseerd bent in de methode en de code dan stuur maar een berichtje.

Groeten,
Jan PE1CID

Re: Adruino Perikelen

Geplaatst: 01 jun 2017, 17:38
door Dopp
Hallo Allemaal,

Klopt gebruik een blokgolf

Maar heb er wel een lowpas filter achter

Natuurlijk kan je een mooiere sinus genereren

met samples enzo...

Maar het gaat mij er om om beginners
op weg te helpen met arduino projectjes enzo...

Ik kan dat ook zelf schrijven maar misschien wel leuk

om jou code hier op dit draadje te zien ....

Bedankt voor de reactie Jan pe1cid

Re: Adruino Perikelen

Geplaatst: 01 jun 2017, 20:35
door PE1CID
Dag Lodewijk,

Ik heb een drietal verschillende CTCSS generatoren gemaakt op basis van Arduino Nano.
1/ Met een dipswitch (zo klein)
2/ Met duimwielschakelaars (gemakkelijker uitlezing)
3/ Met een (mechanische) enocder en een 2 x 8 alfanumeriek display (luxe uitvoering)
De CTCSS generatie is in alle gevallen hetzelfde.

Als bijlage heb ik de software en een aantal foto's toegevoegd. De luxe uitvoering met een encoder en een 2 x 8 alfanumeriek display wordt gebruikt als externe CTCSS generator voor een Kenwood TS-770E. Hiet moet alleen nog in een kastje ingebouwd worden.

Een opmerking betreffende de encoder. Die eenvoudige mechanische encoders denderen nogal en daarom heb ik RC-netwerkjes en antidender in de software toegevoegd.

Als er nog vragen over deze CTCSS generatoren zijn dan hoor ik dat graag.

Groeten,
Jan, PE1CID