Stap 11: Lineaire inductiemotor - macht en besturingselementen
Aanvankelijk hebben we Adafruit motorcontroller schilden gebruikt voor de stroomvoorziening naar de spoelen. De Arduino digitale pennen voorzien 5volts bij een relatief lage stroom. Het schild motorcontroller gebruikt het kleine digitale signaal te sturen van maximaal 1 Amp van macht aan motoren, in dit geval onze spoelen. Gebruik de Adafruit raden die wij ook gebruikt de bibliotheek van Arduino code die ze bieden. Hoewel dit werkte en verplaatst van de auto, bewoog het niet het sterk.
Uiteindelijk hebben we gekozen om te bouwen met behulp van onderdelen van elektronische berging winkels op het gebied van eigen stuurprogramma-bestuur. Met onze eigen Raad van elke spoel circuit is geschikt voor een piek van 8 ampère stroom, en iedere bestuurder kan de macht van de spoelen aan beide zijden van de auto die samen zijn geactiveerd (bedraad parallel). We had met behulp van een 12 volt voeding. Om te vergroten van de macht om de spoelen kochten we een 10 Amp 24 volt voeding. Ze verkopen deze heel goedkoop online voor het aandrijven van LED strips, en ze werken prima voor ons doel.
Voor de definitieve aanpak voor besturingselementen gebruiken we een Arduino Mega aangezien er overvloed van analoge en digitale pennen beschikbaar. De Arduino schets (programma) is is vrij eenvoudig, in die zin dat het een lus rond elke sensor te kijken en te beslissen of er een significante reading is en zo ja, het noorden of zuiden. Als het noorden, van die sensor spoel staat op Zuid (dus het trekken zal). En vice-versa.
Voor de vroege testen gebruiken we een houten autootje op wielen en een enkele set van spoelen. Op een gegeven moment als het begon te werken, waargenomen we "cogging", stotteren van de spoelen trekken op de magneten op een ongelijke wijze. We hadden in de Arduino schets Serial.print opdrachten verzenden lezingen aan de console om te zien wat er gebeurde. Elimineren van de verklaringen van de Serial.print versneld de schets zodat deze de kleine houten auto mooi verplaatst.
Op een ander punt in het testen, wij tijdstempels aan het begin en het einde van de lus om te zien hoe lang alles was. De lus nam 20 tot 25 milliseconden. Dit is veel te traag om te reageren op een auto rijdt met onze gehoopt voor 20 voet per seconde. Ik probeerde de aanroepen naar de bibliotheek van Adafruit nemend en de tijd ging neer tussen 0 en 1 milliseconde. Vooruit dan maar. Dat bevestigde de beslissing te maken van onze eigen macht-chauffeur.
Lijst van gereedschappen en onderdelen
Tools - see general list of Tools Components o 24v 10A Power Supply – Ebay $22 o Arduino Mega – Ebay $20 o Toggle switch o Controller/Driver Board o Part # quantity price cost o TIP122 16 0.59 9.44 o Tip125 16 0.49 7.84 o 1n4148 16 0.05 0.8 o IN5231 16 0.09 1.44 o 2n3904 8 0.12 0.96 o resistors 40 0.04 1.6 o Proto PCB 1 5 5 TOTAL 27.08
Dit is de schets gebruikt voor het uitvoeren van de motoren.
/* LinMotorIndepCoil For use with the Adafruit Motor Shield v2 Version 01 - Independent Sensor/Coil sets, up to 4 sets per motor board Assumes car with PMs is pushed into first sensor/coil pair Permanent magnets are spaced w alternating polarity on car so when pulling on one PM, there will be pushing on the previous. Version 02 - abandon resing/falling tests and use static value of sensors to set coils. Use Serial input to adjust sensor sensitivity Version 03 - log times for coils on/off etc and save timings for print later when interrupt tripped Set timeouts to prevent coils from staying on too long Version 04 - no more Adafruit motor shields - 8 coil pairs */ //#include <Wire.h> int hallPin[] = {0,1,2,3,4,5,6,7}; // analog pins for Hall sensors int coilN[] = { 34, 30, 28, 22, 36, 32, 26, 24 }; // digital pins for setting coil to N int coilS[] = { 35, 31, 29, 23, 37, 33, 27, 25 }; // digital pins for setting coil to S #define HowMany 8 // how many sensor/coil pairs we have int hallVal[] = {0,0,0,0,0,0,0,0 }; //saved values for Hall sensors int hallTrim[] = {0,0,0,0,0,0,0,0 }; // value to be subtracted so // "no field detected" will read 0 #define hallThresh 60 // what reading is significant #define coilMaxTime 1000 //one second should be plenty of time long coilHoldTimeS[HowMany] = {0,0,0,0,0,0,0,0}; // to prevent staying on too long long coilHoldTimeN[HowMany] = {0,0,0,0,0,0,0,0}; // to prevent staying on too long long coilOnTimeS[HowMany] = {0,0,0,0,0,0,0,0}; // when coil came on - first S magnet only long coilOffTimeS[HowMany] = {0,0,0,0,0,0,0,0}; // when coil came off long coilOnTimeN[HowMany] = {0,0,0,0,0,0,0,0}; // when coil came on - first N magnet only long coilOffTimeN[HowMany] = {0,0,0,0,0,0,0,0}; // when coil came off volatile boolean printFlag = false; // flag to indicate button pushed to start printing //long testStart = 0; //long testEnd = 0; //String sense = "0"; void setup() { Serial.begin(9600); // set up Serial library at 9600 bps Serial.println("Starting LinMotorIndepCoil04"); for (int i=0; i< HowMany; i++) { //make sure coils are off pinMode(coilN[i], OUTPUT); digitalWrite(coilN[i], LOW); // set N pin to low pinMode(coilS[i], OUTPUT); digitalWrite(coilS[i], LOW); // set S pin to low } for (int i=0; i < HowMany; i++) { //set sensor trim values assuming no field initially hallTrim[i] = analogRead(hallPin[i]); //sb close to 0 if no field } pinMode(2, INPUT); // set up interrupt on pin 2 digitalWrite(2, HIGH); attachInterrupt(0, setPrintFlag, FALLING); //pin 2 is interrupt 0 } void loop() { //testStart = millis(); if (printFlag == true) printStats(); // button pushed, take time to print stats // look at each of the active sensors to see how its coil should be set for (int i=0; i < HowMany; i++) { int testVal = analogRead(hallPin[i]) - hallTrim[i]; //sb close to 0 if no field if (testVal > hallThresh) { // South pole PM detected // sense = "S"; //Serial.print("South testVal=");Serial.print(testVal); //Serial.print(" i=");Serial.println(i); digitalWrite(coilN[i], HIGH); // set N pin to high digitalWrite(coilS[i], LOW); // set S pin to low coilHoldTimeN[i] = 0; // reset N hold time if (coilHoldTimeS[i] == 0) { coilHoldTimeS[i] = millis(); //save the time } if (coilOnTimeS[i] == 0) { coilOnTimeS[i] = millis(); //save the time for 1st magnet only } if (millis()- coilHoldTimeS[i] > coilMaxTime) { turnOffCoils(i); // if coil has been S too long, turn it off } } else if (testVal < -hallThresh) { // North //sense = "N"; //Serial.print("North testVal=");Serial.print(testVal); //Serial.print(" i=");Serial.println(i); digitalWrite(coilN[i], LOW); // set N pin to low digitalWrite(coilS[i], HIGH); // set S pin to high coilHoldTimeS[i] = 0; // reset S hold time if (coilHoldTimeN[i] == 0) { coilHoldTimeN[i] = millis(); //save the time } if (coilOnTimeN[i] == 0) { coilOnTimeN[i] = millis(); //save the time for 1st magnet only } if (millis()- coilHoldTimeN[i] > coilMaxTime) { turnOffCoils(i); // if coil has been N too long, turn it off } } else { // no signigicant reading // sense = "0"; //Serial.print("Neither testVal=");Serial.print(testVal); //Serial.print(" i=");Serial.println(i); turnOffCoils(i); //they get turned off, // but the coilHoldTime doesn't get reset } } //testEnd = millis(); // Serial.print("test ms=");Serial.print(testEnd - testStart);Serial.print(" ");Serial.println(sense); // delay(2000); } void turnOffCoils(int i) { //Serial.println("turnOffCoils"); digitalWrite(coilN[i], LOW); //turn off the coil digitalWrite(coilS[i], LOW); // if (coilOnTimeS[i] > 0 && coilOffTimeS[i] == 0) { //first time S off for this coil coilOffTimeS[i] = millis(); //time stamp it } if (coilOnTimeN[i] > 0 && coilOffTimeN[i] == 0) { //first time N off for this coil coilOffTimeN[i] = millis(); //time stamp it } // leave coilHoldTime as it is until magnet polarity changes } void setPrintFlag() { //interrupt service routine printFlag = true; } void printStats() { //only do this if interrupt happens for (int i=0; i < HowMany; i++) { //for each of 4 coils Serial.print("Coil "); Serial.print(i+1); Serial.print(" S On Time "); Serial.println(coilOffTimeS[i] - coilOnTimeS[i]); Serial.print("Coil "); Serial.print(i+1); Serial.print(" N On Time "); Serial.println(coilOffTimeN[i] - coilOnTimeN[i]); } printFlag = false; for (int i=0; i < HowMany; i++) { //reset counters after printing coilOnTimeS[i] = 0; coilOnTimeN[i] = 0; coilOffTimeS[i] = 0; coilOffTimeN[i] = 0; } }
Dit is de schets gebruikt voor het testen van de sensoren en spoelen.
/* CoilTest3 to work with hall sensors and our own motor driver board reads all the sensors and prints the value reads input 1-8 from serial and turns that coil to North for 5 seconds */ int hallsave[8]; //no-reading value for setting sensor reading to zero int halls[8]; int coilN[] = { 34,30,28,22,36,32,26,24}; // digital pins for setting coil to N - arranged for jumper geography int coilS[] = { 35,31,29,23,37,33,27,25}; // digital pins for setting coil to S #define howMany 8 void setup() { //while (!Serial); Serial.begin(9600); // set up Serial library at 9600 bps Serial.println("CoilTest3"); Serial.println("Input 1 thru 8 to run specific coil pair for 5 seconds"); for(int i=0;i<howMany;i++) { // save no-reading values hallsave[i] = analogRead(i); } // make sure all coils are off for(int i=0;i<howMany;i++) { pinMode(coilN[i], OUTPUT); digitalWrite(coilN[i], LOW); pinMode(coilS[i], OUTPUT); digitalWrite(coilS[i], LOW); } } // int i; void loop() { for(int i=0;i<howMany;i++) { halls[i] = analogRead(i) - hallsave[i]; //sb close to 0 if no field Serial.print(halls[i]); Serial.print(" "); // debug value } Serial.println(""); delay(1000); char cmd ; if (Serial.available()) { cmd = Serial.read(); //read character from serial } else return; if (cmd >= '1' && cmd <='8') { int x=cmd-48; digitalWrite(coilN[x - 1], HIGH); // turn on coil set to N Serial.print("testing #"); Serial.println(x); delay(2000); Serial.println("off"); digitalWrite(coilN[x-1], LOW); // turn off both coils of pair } }