Wind Turbine Control System
The purpose of the control system is to reduce the effective load resistance
across the generator so that the generator can reach it’s desired speed of 4500 RPM. If the the load resistance across the generator is low, the generator will spin faster compared to when the load resistance is high. Reduction of load resistance is achieved by rapidly opening and closing the charging circuit; a technique also known as PWM (Pulse Width Modulation).
The Arduino micro-controller sends a PWM signal to a solid state relay, IRF510, to reduce the effective load resistance. The PWM signal has a magnitude or duty cycle that is proportional to blade speed: low PWM duty cycle (0) implies low effective load resistance and low resistive torque on generator whilst high PWM duty cycle (255) implies high effective load resistance and highest resistive torque on generator. The Arduino reduces effective load resistance only if blade speed is less than 4500 RPM; if blade speed is above 4500 RPM, the Arduino sends a PWM signal of magnitude 255 to maximize effective load resistance. The Arduino software the we used can be downloaded here.
Arduino code
// Author : J.Kadoko // ME 43 Wind Turbine Design Project // Here is the pin layout /* Digital pins: 1 - Nothing 2 - Encoder (interupt 1) 3 - LCD Screen (DB7) 4 - LCD Screen (DB 6) 5 - LCD Screen (DB 5) 6 - LCD Screen (DB 4) 7 - LCD Screen (Enable Pin) 8 - LCD Screen (RS) 9 - Nothing 10 - Kick-start Transistor 11 - PWM Load Transistor Analog Pins : 0 - voltage across the generator reading 1 - Nothing 2 - nothing 3 - Nothing 4 - Nothing 5 - Nothing */ /* Description: The turbine is expected to run at a speed of 4500RPM at wind speed of 10m/s in the wind tunnel. As the wind turbine is starting, the arduino will kick-start the generator by running it as a motor. The Arduino controls a transistor that opens and closes a circuit. During kick-starting, the PWM transistor should be open. Kick-starting will be short pulses of until the generator is rotating on its own due to wind. As the generator rotates on its own, the Arduino will lessen the load (and hence the overall power extracted from the generator) by PWMing the load so that the generator can get up to the desired speed of 4500rpm. Pin 11 controls the transistor that does PWM. Results: Not all of the desired features were implemented in the first iteration because of time limitations. The controller was not implemented because the encoder saturated at blade speeds of 1000RPM - we hope to spec a new encoder. The push buttons and kick-starting system were not implemented because there was no need to kick-start the generator; it had a cut-in speed of 3m/s Current measurements were not implemented because of time constraints Voltage measurement system was implemented during experiments but it is not yet perfect. This code was used for demonstration on December 9, 2011 at the CEEO (Tufts University). It provides a good starting point for people interested in further developing WhaleWurbine's Control system or learning about our design process. */ // Libraries #include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins LiquidCrystal lcd(8, 7, 6, 5, 4, 3); // Other pins : int voltSensor = A1; // voltage across a 330k Ohm resistor , back calculate this to obtain the actual voltage across the generator int loadPWM = 11; // PWM the load - controls the transistor int kickStart = 10; // Kick- start transistor const int encoder = 2; // Variables : float w = 0; // expected blade speed (rd/s) double wD = 40; // the desired blade speed (rd/s) 471 is the 4500 rpm double v = 0; // voltage across the generator (V) double vD = 5; // desired voltage across the generator (V) double kV = 0.01; // the kV value of the motor [V/(rd/s)]; long currTime = 0; // time in milliseconds long oldTime1 = 0; // time in milliseconds used for speed long oldTime2 = 0; // time in milliseconds used for pwm float dt = 0; // change in time (s) int RL = 0; // pwm output for the load transistor double integral = 0; // the integral term in the generator; double ki = 1; // integral constant double kp = 0.01; // proportional constant double error = 0; double theta = 0; // the counter of the rotating disk double thetaOld = 0; // the old counter value of theta double current = 0; // I am not sure yet how we can measure this double R = 0.1; // radius of the encoder disk long R1 = 330000; // this is the resistor that goes from Vout to ground on the potential devider (Ohms) long R2 = 470000; // this is the resistor that goes from Vout to v Volts of the generator (Ohms); // I will do a state machine int state = 0; int mode = 0; // mode 0 controls the turbine with voltage , mode 1 controlls the turbine using blade speed const int kickState = 1; const int pwmState = 2; const int chargeState = 3; void setup() { // set the cursor to (0,0): lcd.begin(16, 2); lcd.print("ME 43 Design"); // Start Serial port communication Serial.begin(9600); // declare the pin modes: pinMode(voltSensor, INPUT); pinMode(loadPWM, OUTPUT); pinMode(kickStart, OUTPUT); attachInterrupt(0, bladeSpeed, RISING); // print welcome message delay(5); // initialize variables currTime = millis(); } void loop() { //CALCULATIONS : if (theta > thetaOld) { currTime = micros(); dt = (currTime - oldTime1) / 1000000.0; // calculate the speed of the blades in rd/s w = (theta - thetaOld) * 3.14 / dt; oldTime1 = currTime; thetaOld = theta; } // select the right state based on the mode : mode 0 uses voltage readings to estimate w; mode 1 uses photointerruptor to calculate v = analogRead(voltSensor); v = v * 2.4242 / 1024.0; // voltage across the generator (V) should be measured across a potential devider with R1 and R2; v = map(v, 0.14, 0.22, 1, 7); if (mode == 0) { if (v == 0) // should change this depending on what the input noise is { state = kickState; // kick-start the generator } else if ( v < vD) { state = pwmState; } else if (v > vD) { state = chargeState; } } else { if (w == 0) { state = kickState; // kick-start the generator } else if (w < wD) { state = pwmState; } else if (w > wD) { state = chargeState; } } // stuff into the serial stream: Serial.print(w); Serial.print(", voltage"); Serial.print(v); Serial.print(",state"); Serial.println(state); // stuff to the user: lcd.setCursor(0, 1); //lcd.print("Volt:"); lcd.print(w); lcd.setCursor(5, 1); lcd.print("rd/s"); delay(100); switch (state) { case kickState: analogWrite(loadPWM, 0); // open the loadPWM digitalWrite(kickStart, HIGH); // close the kick starting circuit delay(10); // delay for a few milliseconds digitalWrite(kickStart, LOW); // turn off the kick starting circuit case pwmState: currTime = millis(); dt = (currTime - oldTime2) / 1000; // calculate the error signal error = vD - v; // vDesired - vMeasured integral = integral + error * dt; // Integral term // output RL = integral * ki + kp * error; // coerce the resistance to 255 if (RL > 255) { RL = 255; } else if (RL < 0) { RL = 0; } digitalWrite(kickStart, LOW); // turn off the kick starting analogWrite(loadPWM, 100); // play with the duty cycle depending on what the voltage or blade speed is oldTime2 = currTime; case chargeState: // everything is good - go ahead and charge the battery !!! digitalWrite(kickStart, LOW); analogWrite(loadPWM, 255); default: lcd.setCursor(0, 1); //lcd.print("Check Wire Connections !!"); } } void bladeSpeed() { theta = theta + 1; }