4Motus DIY Überbike Part3
Zusammenbau Teil 3
So nach zwei kleinen “Zwangspausen” (=kaputter Controller/einige malträtierte Gliedmassen und ein gebrochener Daumen) kommt mal wieder ein Update – wahrscheinlich das Zweitletzte 😉
Um das Gesamtbild des Bikes ein wenig zu verbessern, habe ich mich dazu entschieden, die Feder, die Pedalen sowie den Lenker udn den Vorbau ebenfalls zu Pulvern.
Ein 23mm grosses Loch mit dem Schälbohrer zu bohren ist, gar nicht mal so einfach. Es hat schlussendlich aber doch geklappt. Später wird darin ein Neutrik Speakon als Ladeport hausen.
Keine Ahnung wie viele Meter Kabel in der Box verstaut werden, auf jeden Fall sind es einige.
Ready zur Testfahrt. Auf der Seite hängt ein Greentime Controller, den ich zum Test angehängt habe. Das Bike funktionierte mehr oder weniger gut, man merkt jedoch, dass die interne Regelung nicht wirklich gut ist. Das Motorgeräusch ist sehr deutlich hörbar und der Motor stottert ganz leicht bei hohen und sehr tiefen Geschwindigkeiten. Dummerweise drehte der Motor bei gleichem Phasen- und Hallsensor-Anschluss rückwärts und nicht vorwärts wie beim Sabvoton Controller. Das habe ich auch gleich zu spüren bekommen, als sich die Pedale in meinem Knie vergraben hat. Naja, die Freude über die Funktion war natürlich grösser als der Schmerz und so konnte ich eine kurze Testfahrt machen. Es geht schon gut ab, aber ist noch sehr gut handlebar.
Der Gasgriff-Controller: Das Bike kann nun mit einem RFID Tag ensperrt werden. Es gibt 3 Modi: Nach dem Einschalten kann das Bike nur mit den Pedalen gefahren werden. Der Gasgriff ist nutzlos. Modus 2: Mit einem RFID Tag kann das Bike in den strassenlegalen Modus geschaltet werden. Die Leistung wird dabei auf ca. 1kW und die Geschwindigkeit auf 45km/h beschränkt. Modus 3: Das Bike ist komplett entsperrt.
Ebenso ist es möglich die Rekuperation stufenlos einzustellen. Wenn man die Bremse zieht, stellt der Controller auf Rekuperation um. Der Gasgriff fungiert dann als Bremsgriff. Eine Sicherheitsfunktion muss jedoch noch implementiert werden: Wenn beim Bremsen der Gasgriff voll auf ist und die Bremse wieder losgelassen wird, muss der Gasgriff zuerst in die Nullstellung gebracht werden, bevor er wieder als Gasgriff fungieren kann. So wird vermieden, dass versehentlich vollgas gegeben werden kann, wenn die Bremse gelöst wird. Ev. kann auf dieses Feature verzichtet werden, wenn die Stromrampe im Controller genügend lange ist.
Nachtrag: Es reicht, die Drehmomentrampe im Controller auf 1800ms zu stellen. Die Rampe fühlt sich so an, als würde sie exponentionell ansteigen und dann in die Sättigung gehen. Die Leistung kann auch so bei niedrigen Drehzahlen sehr gut dosiert werden.
/* 4motus überbike throttle and brake controller Created by chuleo */ #include <SPI.h> #define uchar unsigned char #define uint unsigned int //data array maxium length #define MAX_LEN 16 ///////////////////////////////////////////////////////////////////// //set the pin ///////////////////////////////////////////////////////////////////// const int chipSelectPin = 10; const int NRSTPD = 5; int sensorPin = A0; // select the input pin for the potentiometer int ledPin = 13; // select the pin for the LED int outPin = 5; int brakeOut = 6; int brakeIn = 2; int speedLim = 7; int sensorValue = 0; // variable to store the value coming from the sensor int brakeVal; //MF522 command bits #define PCD_IDLE 0x00 //NO action; cancel current commands #define PCD_AUTHENT 0x0E //verify password key #define PCD_RECEIVE 0x08 //receive data #define PCD_TRANSMIT 0x04 //send data #define PCD_TRANSCEIVE 0x0C //send and receive data #define PCD_RESETPHASE 0x0F //reset #define PCD_CALCCRC 0x03 //CRC check and caculation //Mifare_One card command bits #define PICC_REQIDL 0x26 //Search the cards that not into sleep mode in the antenna area #define PICC_REQALL 0x52 //Search all the cards in the antenna area #define PICC_ANTICOLL 0x93 //prevent conflict #define PICC_SElECTTAG 0x93 //select card #define PICC_AUTHENT1A 0x60 //verify A password key #define PICC_AUTHENT1B 0x61 //verify B password key #define PICC_READ 0x30 //read #define PICC_WRITE 0xA0 //write #define PICC_DECREMENT 0xC0 //deduct value #define PICC_INCREMENT 0xC1 //charge up value #define PICC_RESTORE 0xC2 //Restore data into buffer #define PICC_TRANSFER 0xB0 //Save data into buffer #define PICC_HALT 0x50 //sleep mode //THe mistake code that return when communicate with MF522 #define MI_OK 0 #define MI_NOTAGERR 1 #define MI_ERR 2 //------------------MFRC522 register --------------- //Page 0:Command and Status #define Reserved00 0x00 #define CommandReg 0x01 #define CommIEnReg 0x02 #define DivlEnReg 0x03 #define CommIrqReg 0x04 #define DivIrqReg 0x05 #define ErrorReg 0x06 #define Status1Reg 0x07 #define Status2Reg 0x08 #define FIFODataReg 0x09 #define FIFOLevelReg 0x0A #define WaterLevelReg 0x0B #define ControlReg 0x0C #define BitFramingReg 0x0D #define CollReg 0x0E #define Reserved01 0x0F //Page 1:Command #define Reserved10 0x10 #define ModeReg 0x11 #define TxModeReg 0x12 #define RxModeReg 0x13 #define TxControlReg 0x14 #define TxAutoReg 0x15 #define TxSelReg 0x16 #define RxSelReg 0x17 #define RxThresholdReg 0x18 #define DemodReg 0x19 #define Reserved11 0x1A #define Reserved12 0x1B #define MifareReg 0x1C #define Reserved13 0x1D #define Reserved14 0x1E #define SerialSpeedReg 0x1F //Page 2:CFG #define Reserved20 0x20 #define CRCResultRegM 0x21 #define CRCResultRegL 0x22 #define Reserved21 0x23 #define ModWidthReg 0x24 #define Reserved22 0x25 #define RFCfgReg 0x26 #define GsNReg 0x27 #define CWGsPReg 0x28 #define ModGsPReg 0x29 #define TModeReg 0x2A #define TPrescalerReg 0x2B #define TReloadRegH 0x2C #define TReloadRegL 0x2D #define TCounterValueRegH 0x2E #define TCounterValueRegL 0x2F //Page 3:TestRegister #define Reserved30 0x30 #define TestSel1Reg 0x31 #define TestSel2Reg 0x32 #define TestPinEnReg 0x33 #define TestPinValueReg 0x34 #define TestBusReg 0x35 #define AutoTestReg 0x36 #define VersionReg 0x37 #define AnalogTestReg 0x38 #define TestDAC1Reg 0x39 #define TestDAC2Reg 0x3A #define TestADCReg 0x3B #define Reserved31 0x3C #define Reserved32 0x3D #define Reserved33 0x3E #define Reserved34 0x3F //----------------------------------------------- //4 bytes Serial number of card, the 5 bytes is verfiy bytes uchar serNum[5]; static int unlocked = 2; static int maxpower = 100; int throttle_pin = 0; int throttle_val; //buffer A password, 16 buffer, the passowrd of every buffer is 6 byte uchar sectorKeyA[16][16] = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, //{0x19, 0x84, 0x07, 0x15, 0x76, 0x14}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, }; uchar sectorNewKeyA[16][16] = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xff,0x07,0x80,0x69, 0x19,0x84,0x07,0x15,0x76,0x14}, //you can set another ket , such as " 0x19, 0x84, 0x07, 0x15, 0x76, 0x14 " //{0x19, 0x84, 0x07, 0x15, 0x76, 0x14, 0xff,0x07,0x80,0x69, 0x19,0x84,0x07,0x15,0x76,0x14}, // but when loop, please set the sectorKeyA, the same key, so that RFID module can read the card {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xff,0x07,0x80,0x69, 0x19,0x33,0x07,0x15,0x34,0x14}, }; void setup() { pinMode(chipSelectPin,OUTPUT); // Set digital pin 10 as OUTPUT to connect it to the RFID /ENABLE pin pinMode(ledPin, OUTPUT); pinMode(outPin, OUTPUT); pinMode(brakeOut, OUTPUT); pinMode(brakeIn, INPUT); pinMode(speedLim, OUTPUT); digitalWrite(chipSelectPin, LOW); // Activate the RFID reader digitalWrite(NRSTPD, HIGH); digitalWrite(speedLim, HIGH); //Speedlimit is deactivated by default //brakeVal=digitalRead(brakeIn); Serial.begin(9600); // RFID reader SOUT pin connected to Serial RX pin at 9600bps SPI.begin(); setPwmFrequency(5, 1); //set pwm frequency to 62khz (output needs less filtering with a high pwm freq.) MFRC522_Init(); } void loop() { uchar i,tmp; uchar status; uchar str[MAX_LEN]; uchar RC_size; uchar blockAddr; //Select operation buck address 0 - 63 String mynum = ""; int breaking; sensorValue=analogRead(sensorPin)/4; //throttle input. if unlocked = 0 then max throttle out= maxpower breaking=map(sensorValue,0,256,48,208); //breaking begins at approx. 1.5V -> needs an offset. //if breaking is 5V it will stop breaking (detects hardware fault) if(unlocked==0){ //if unlocked=1 then max speed = throttle if((sensorValue)<=maxpower){ analogWrite(outPin,sensorValue); analogWrite(brakeOut,breaking); } else{ analogWrite(outPin,maxpower); analogWrite(brakeOut,breaking); //max braking power should be the same at any time } } else if(unlocked==1){ analogWrite(outPin,sensorValue); analogWrite(brakeOut,breaking); //Serial.println(sensorValue); } else if(unlocked==2){ //default state, bike soesnt move analogWrite(outPin,10); analogWrite(brakeOut,10); } if(unlocked==2){ //default on startup, reads rfid constantly, slows analog read from throttle down //Search card, return card types status = MFRC522_Request(PICC_REQIDL, str); if (status == MI_OK){ } //Prevent conflict, return the 4 bytes Serial number of the card status = MFRC522_Anticoll(str); memcpy(serNum, str, 5); if (status == MI_OK) { Serial.println("The card's number is : "); Serial.print(serNum[0]); Serial.print(" , "); Serial.print(serNum[1]); Serial.print(" , "); Serial.print(serNum[2]); Serial.print(" , "); Serial.print(serNum[3]); Serial.print(" , "); Serial.print(serNum[4]); Serial.println(" "); // Should really check all pairs, but for now we'll just use the first if(serNum[0] == 111 && serNum[1] == 111 && serNum[2]==111 && serNum[3]==111) { unlocked=1; } else if(serNum[0] == 111 && serNum[1] == 111 && serNum[2]==111 && serNum[3]==111){ unlocked=0; //that means bike runs with speed limit digitalWrite(speedLim,LOW); } else{ } // delay(1000); } //Serial.println(" "); MFRC522_Halt(); //command the card into sleep mode } else {} } void setPwmFrequency(int pin, int divisor) { byte mode; if(pin == 5 || pin == 6 || pin == 9 || pin == 10) { switch(divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 64: mode = 0x03; break; case 256: mode = 0x04; break; case 1024: mode = 0x05; break; default: return; } if(pin == 5 || pin == 6) { TCCR0B = TCCR0B & 0b11111000 | mode; } else { TCCR1B = TCCR1B & 0b11111000 | mode; } } else if(pin == 3 || pin == 11) { switch(divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 32: mode = 0x03; break; case 64: mode = 0x04; break; case 128: mode = 0x05; break; case 256: mode = 0x06; break; case 1024: mode = 0x7; break; default: return; } TCCR2B = TCCR2B & 0b11111000 | mode; } } /* * Function:Write_MFRC5200 * Description:write a byte data into one register of MR RC522 * Input parameter:addr--register address;val--the value that need to write in * Return:Null */ void Write_MFRC522(uchar addr, uchar val) { digitalWrite(chipSelectPin, LOW); //address format:0XXXXXX0 SPI.transfer((addr<<1)&0x7E); SPI.transfer(val); digitalWrite(chipSelectPin, HIGH); } /* * Function:Read_MFRC522 * Description:read a byte data into one register of MR RC522 * Input parameter:addr--register address * Return:return the read value */ uchar Read_MFRC522(uchar addr) { uchar val; digitalWrite(chipSelectPin, LOW); //address format:1XXXXXX0 SPI.transfer(((addr<<1)&0x7E) | 0x80); val =SPI.transfer(0x00); digitalWrite(chipSelectPin, HIGH); return val; } /* * Function:SetBitMask * Description:set RC522 register bit * Input parameter:reg--register address;mask--value * Return:null */ void SetBitMask(uchar reg, uchar mask) { uchar tmp; tmp = Read_MFRC522(reg); Write_MFRC522(reg, tmp | mask); // set bit mask } /* * Function:ClearBitMask * Description:clear RC522 register bit * Input parameter:reg--register address;mask--value * Return:null */ void ClearBitMask(uchar reg, uchar mask) { uchar tmp; tmp = Read_MFRC522(reg); Write_MFRC522(reg, tmp & (~mask)); // clear bit mask } /* * Function:AntennaOn * Description:Turn on antenna, every time turn on or shut down antenna need at least 1ms delay * Input parameter:null * Return:null */ void AntennaOn(void) { uchar temp; temp = Read_MFRC522(TxControlReg); if (!(temp & 0x03)) { SetBitMask(TxControlReg, 0x03); } } /* * Function:AntennaOff * Description:Turn off antenna, every time turn on or shut down antenna need at least 1ms delay * Input parameter:null * Return:null */ void AntennaOff(void) { ClearBitMask(TxControlReg, 0x03); } /* * Function:ResetMFRC522 * Description: reset RC522 * Input parameter:null * Return:null */ void MFRC522_Reset(void) { Write_MFRC522(CommandReg, PCD_RESETPHASE); } /* * Function:InitMFRC522 * Description:initilize RC522 * Input parameter:null * Return:null */ void MFRC522_Init(void) { digitalWrite(NRSTPD,HIGH); MFRC522_Reset(); //Timer: TPrescaler*TreloadVal/6.78MHz = 24ms Write_MFRC522(TModeReg, 0x8D); //Tauto=1; f(Timer) = 6.78MHz/TPreScaler Write_MFRC522(TPrescalerReg, 0x3E); //TModeReg[3..0] + TPrescalerReg Write_MFRC522(TReloadRegL, 30); Write_MFRC522(TReloadRegH, 0); Write_MFRC522(TxAutoReg, 0x40); //100%ASK Write_MFRC522(ModeReg, 0x3D); //CRC initilizate value 0x6363 ??? //ClearBitMask(Status2Reg, 0x08); //MFCrypto1On=0 //Write_MFRC522(RxSelReg, 0x86); //RxWait = RxSelReg[5..0] //Write_MFRC522(RFCfgReg, 0x7F); //RxGain = 48dB AntennaOn(); //turn on antenna } /* * Function:MFRC522_Request * Description:Searching card, read card type * Input parameter:reqMode--search methods, * TagType--return card types * 0x4400 = Mifare_UltraLight * 0x0400 = Mifare_One(S50) * 0x0200 = Mifare_One(S70) * 0x0800 = Mifare_Pro(X) * 0x4403 = Mifare_DESFire * return:return MI_OK if successed */ uchar MFRC522_Request(uchar reqMode, uchar *TagType) { uchar status; uint backBits; //the data bits that received Write_MFRC522(BitFramingReg, 0x07); //TxLastBists = BitFramingReg[2..0] ??? TagType[0] = reqMode; status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits); if ((status != MI_OK) || (backBits != 0x10)) { status = MI_ERR; } return status; } /* * Function:MFRC522_ToCard * Description:communicate between RC522 and ISO14443 * Input parameter:command--MF522 command bits * sendData--send data to card via rc522 * sendLen--send data length * backData--the return data from card * backLen--the length of return data * return:return MI_OK if successed */ uchar MFRC522_ToCard(uchar command, uchar *sendData, uchar sendLen, uchar *backData, uint *backLen) { uchar status = MI_ERR; uchar irqEn = 0x00; uchar waitIRq = 0x00; uchar lastBits; uchar n; uint i; switch (command) { case PCD_AUTHENT: //verify card password { irqEn = 0x12; waitIRq = 0x10; break; } case PCD_TRANSCEIVE: //send data in the FIFO { irqEn = 0x77; waitIRq = 0x30; break; } default: break; } Write_MFRC522(CommIEnReg, irqEn|0x80); //Allow interruption ClearBitMask(CommIrqReg, 0x80); //Clear all the interrupt bits SetBitMask(FIFOLevelReg, 0x80); //FlushBuffer=1, FIFO initilizate Write_MFRC522(CommandReg, PCD_IDLE); //NO action;cancel current command ??? //write data into FIFO for (i=0; i<sendLen; i++) { Write_MFRC522(FIFODataReg, sendData[i]); } //procceed it Write_MFRC522(CommandReg, command); if (command == PCD_TRANSCEIVE) { SetBitMask(BitFramingReg, 0x80); //StartSend=1,transmission of data starts } //waite receive data is finished i = 2000; //i should adjust according the clock, the maxium the waiting time should be 25 ms??? do { //CommIrqReg[7..0] //Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq n = Read_MFRC522(CommIrqReg); i--; } while ((i!=0) && !(n&0x01) && !(n&waitIRq)); ClearBitMask(BitFramingReg, 0x80); //StartSend=0 if (i != 0) { if(!(Read_MFRC522(ErrorReg) & 0x1B)) //BufferOvfl Collerr CRCErr ProtecolErr { status = MI_OK; if (n & irqEn & 0x01) { status = MI_NOTAGERR; //?? } if (command == PCD_TRANSCEIVE) { n = Read_MFRC522(FIFOLevelReg); lastBits = Read_MFRC522(ControlReg) & 0x07; if (lastBits) { *backLen = (n-1)*8 + lastBits; } else { *backLen = n*8; } if (n == 0) { n = 1; } if (n > MAX_LEN) { n = MAX_LEN; } //read the data from FIFO for (i=0; i<n; i++) { backData[i] = Read_MFRC522(FIFODataReg); } } } else { status = MI_ERR; } } //SetBitMask(ControlReg,0x80); //timer stops //Write_MFRC522(CommandReg, PCD_IDLE); return status; } /* * Function:MFRC522_Anticoll * Description:Prevent conflict, read the card serial number * Input parameter:serNum--return the 4 bytes card serial number, the 5th byte is recheck byte * return:return MI_OK if successed */ uchar MFRC522_Anticoll(uchar *serNum) { uchar status; uchar i; uchar serNumCheck=0; uint unLen; //ClearBitMask(Status2Reg, 0x08); //TempSensclear //ClearBitMask(CollReg,0x80); //ValuesAfterColl Write_MFRC522(BitFramingReg, 0x00); //TxLastBists = BitFramingReg[2..0] serNum[0] = PICC_ANTICOLL; serNum[1] = 0x20; status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen); if (status == MI_OK) { //Verify card serial number for (i=0; i<4; i++) { serNumCheck ^= serNum[i]; } if (serNumCheck != serNum[i]) { status = MI_ERR; } } //SetBitMask(CollReg, 0x80); //ValuesAfterColl=1 return status; } /* * Function:CalulateCRC * Description:Use MF522 to caculate CRC * Input parameter:pIndata--the CRC data need to be read,len--data length,pOutData-- the caculated result of CRC * return:Null */ void CalulateCRC(uchar *pIndata, uchar len, uchar *pOutData) { uchar i, n; ClearBitMask(DivIrqReg, 0x04); //CRCIrq = 0 SetBitMask(FIFOLevelReg, 0x80); //Clear FIFO pointer //Write_MFRC522(CommandReg, PCD_IDLE); //Write data into FIFO for (i=0; i<len; i++) { Write_MFRC522(FIFODataReg, *(pIndata+i)); } Write_MFRC522(CommandReg, PCD_CALCCRC); //waite CRC caculation to finish i = 0xFF; do { n = Read_MFRC522(DivIrqReg); i--; } while ((i!=0) && !(n&0x04)); //CRCIrq = 1 //read CRC caculation result pOutData[0] = Read_MFRC522(CRCResultRegL); pOutData[1] = Read_MFRC522(CRCResultRegM); } /* * Function:MFRC522_SelectTag * Description:Select card, read card storage volume * Input parameter:serNum--Send card serial number * return:return the card storage volume */ uchar MFRC522_SelectTag(uchar *serNum) { uchar i; uchar status; uchar size; uint recvBits; uchar buffer[9]; //ClearBitMask(Status2Reg, 0x08); //MFCrypto1On=0 buffer[0] = PICC_SElECTTAG; buffer[1] = 0x70; for (i=0; i<5; i++) { buffer[i+2] = *(serNum+i); } CalulateCRC(buffer, 7, &buffer[7]); //?? status = MFRC522_ToCard(PCD_TRANSCEIVE, buffer, 9, buffer, &recvBits); if ((status == MI_OK) && (recvBits == 0x18)) { size = buffer[0]; } else { size = 0; } return size; } /* * Function:MFRC522_Auth * Description:verify card password * Input parameters:authMode--password verify mode 0x60 = verify A passowrd key 0x61 = verify B passowrd key BlockAddr--Block address Sectorkey--Block password serNum--Card serial number ,4 bytes * return:return MI_OK if successed */ uchar MFRC522_Auth(uchar authMode, uchar BlockAddr, uchar *Sectorkey, uchar *serNum) { uchar status; uint recvBits; uchar i; uchar buff[12]; //Verify command + block address + buffer password + card SN buff[0] = authMode; buff[1] = BlockAddr; for (i=0; i<6; i++) { buff[i+2] = *(Sectorkey+i); } for (i=0; i<4; i++) { buff[i+8] = *(serNum+i); } status = MFRC522_ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits); if ((status != MI_OK) || (!(Read_MFRC522(Status2Reg) & 0x08))) { status = MI_ERR; } return status; } /* * Function:MFRC522_Read * Description:Read data * Input parameters:blockAddr--block address;recvData--the block data which are read * return:return MI_OK if successed */ uchar MFRC522_Read(uchar blockAddr, uchar *recvData) { uchar status; uint unLen; recvData[0] = PICC_READ; recvData[1] = blockAddr; CalulateCRC(recvData,2, &recvData[2]); status = MFRC522_ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen); if ((status != MI_OK) || (unLen != 0x90)) { status = MI_ERR; } return status; } /* * Function:MFRC522_Write * Description:write block data * Input parameters:blockAddr--block address;writeData--Write 16 bytes data into block * return:return MI_OK if successed */ uchar MFRC522_Write(uchar blockAddr, uchar *writeData) { uchar status; uint recvBits; uchar i; uchar buff[18]; buff[0] = PICC_WRITE; buff[1] = blockAddr; CalulateCRC(buff, 2, &buff[2]); status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits); if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) { status = MI_ERR; } if (status == MI_OK) { for (i=0; i<16; i++) //Write 16 bytes data into FIFO { buff[i] = *(writeData+i); } CalulateCRC(buff, 16, &buff[16]); status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits); if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) { status = MI_ERR; } } return status; } /* * Function:MFRC522_Halt * Description:Command the cards into sleep mode * Input parameters:null * return:null */ void MFRC522_Halt(void) { uchar status; uint unLen; uchar buff[4]; buff[0] = PICC_HALT; buff[1] = 0; CalulateCRC(buff, 2, &buff[2]); status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff,&unLen); }
Natürlich wäre ein Drehmomentsensor viel eleganter… leider sind diese auch viel teurer (ab 200.-) In meinem Fall unterstützt das Bike auch, wenn man “pseudopedaliert”. Bei einigen Baumarkt Pedelecs ist dies ebenfalls so. Da ich nur einen Gang habe, macht es auch keinen Sinn die Tretunterstützung über die Kadenz anzupassen. Die Leistungsregelung erfolgt adaptiv über den Gasgriff.
Sabvoton Einstellungen
Wie bei allen China Controllern ist die Dokumentation schon ziemlich dürftig und teilweise fehlerhaft. Deshalb beschreibe ich hier ganz kurz das erbärmliche Chinglish Labview Interface und das wiring diagram des Controllers. Ebenso ist das Bluetooth Interface wirklich unbrauchbar: Die Android App stürzt dauernd ab und die Kommunikation funktioniert, wenn überhaupt, nur sporadisch. Ich werde aber nur die wichtigsten Funktionen erläutern. Das Diagramm zeigt eigentlich die 96V Variante des Controllers. Die linke Seite muss man nicht beachten.
- Blaues Hallsensor Kabel (Funktion unbekannt)
- Beide Throttle reagieren auf ein analoges 0-5V Signal. Wobei der nutzbare Bereich eingestellt werden kann. I.d.R. liest der Controller eine eher zu hohe Spannung ein. Fällt die Spannung auf 0V oder steigt sie auf 5V so schaltet der Motor ab und der Controller gibt einen Fehler aus.
- Die Signale Cruise, Reverse und Boost werden aktiviert wenn man sie auf 0V zieht
- Das High brake Signal muss min 5V sein um aktiv zu sein. Anscheinend kann es auch auf die positive Batteriespannung gezogen werden ohne den Controller zu beschädigen.
- Das Electric lock ist eigentlich die Speisung des Controllers (Orange oder Rot)
- Ein pinkes Kabel wird entweder das Low brake oder das Speed Limit Signal sein
Die Basic Funktionen sind eigentlich selbsterklärend: Lack Volt ist die Spannung bei der der Controller den Dienst quittiert. Idealerweise wird der Phasenstrom auf ca. 2.5x Batteriestrom gesetzt.
Die Temperaturfunktionen muss ich wohl nicht erläutern. Wenn die variable Rekuperation benutzt wird, müssen General brake disabled und Electric brake enabled sein. Flux weakening ist nützlich um eine höhere Geschwindigkeit auf Kosten der Reichweite zu erzielen. Wenn Slide recharge enabled ist, rekuperiert der Controller sobald der Gasgriff losgelassen wird. Der Grenzwert bei dem der Slide recharge noch funktioniert kann mit dem Slide recharge speed eingestellt werden.
Wichtig: Der Controller scheint den Electric brake ph current falsch einzulesen: Wenn man mit bis zu 50A Phasenstrom rekuperieren will, muss der Wert auf 500 gesetzt werden! (Zumindest in der ewig aktuellen Softwareversion). Electric brake wird eingeschaltet wenn das High brake Signal auf 5V+ gezogen wird. Mit dem Variable Regen wird der Phasenstrom eingestellt.
Der Throttle min vol darf nicht zu tief eingestellt werden, ansonsten dreht sich der Motor, wenn der Gasgriff nicht betätigt wird. 1.3-1.4V sind üblich (auch wenn der Gasgriff nur 0.8V ausgibt!)
Die Accelerate time ist die Zeit, die es dauert, bis der Phasenstrom von 0-max geht. Um Wheelies beim Anfahren zu vermeiden, sollte der Wert am Anfang auf 2000ms (Maximalwert) und die Decelerate time auf 50ms gesetzt werden.
Falls man ein Kabel hat, um die Geschwindigkeit zu begrenzen, kann man unter Motor limit speed set den Wert einstellen. (Der Wert gilt, wenn das Signal -auch nur temporär- auf 0V gezogen wird).
Low/Middle speed set sind für den Fall, dass ein 3 Speed Switch installiert wurde.
Was ich am Anfang übersehen habe war der Parameter store Schalter. Wenn man die Einstellungen auch speichern will, so muss man nach jeder neuen Eingabe zuerst OK neben dem Wert drücken und anschliessend im Debug Register, den Parameter store Schalter umlegen und dann OK drücken.
Hallo,
ich habe mir vor kurzem ein ControllerKIT geholt und hab arge probleme den conntroller mit dem rechner zu verbinden . comport richtig gewählt und alles.
wenn ich das usb-kabel am Controller abziehe ist der Blinkintervall der TX-LED in der software länger.Also passiert schon mal was. aber die verfluchte RX-LED blinkt zu keiner zeit uns somit auch keine rückmeldung und einstellungsmöglichkeit.
was auch noch irritierend ist, beim betätigen der bremsgriffe wird der motor zwarabgeschaltet aber die bremswirkung fehlt.
Ich hoffe Du liest dieses hier und antwortest schnell 🙂
Controller MQ72080
bin schon am verzweifel 🙁
mfg
Martin
Was steht denn im Feld system status? Hast du das USB Kabel auch richtig angeschlossen? (Das dicke Ende kommt an den PC und das dünne Ende an den Controller). Das mit den Bremsgriffen ist schon richtig so. Damit der Controller beim ziehen der Bremsen auch bremst, musst du im Menü Func auch electric brake aktivieren und unter eletric brake current den Strom einstellen.
Hallo,
das ist alles richtig , was Du sagst. Ich bekomme nur durch die fehlende kommunikation zucontroller keinen zugriff. das dicke ende des kabels wo das modem drin verbaut ist, steckt im PC …andersherum wird es auch nicht erkannt und man kann keinen comport einstellen.
da die kommunikation über diesen chat hier sehr langwierig ist, würde ich vorschlagen (wenn es Dir nichts ausmacht) das wenn möglich wir mal telefonieren . 0172/2895727 (ich kann dich auch gerne wegen der koasten zurückrufen. vielen Dank schon mal für deine mail.
mfg
martin
Ich sehe im Moment auch keine Möglichkeit wie ich dir helfen kann. Ev ist einfach dein Kabel defekt? Prinzipiell sollte jeder USB->Seriell Adapter funktionieren. Welche Software Version verwendest du denn? Die von der Sabvoton Homepage oder die März Version (https://www.dropbox.com/sh/l19efzir6w5eoqu/AABLLK1P-WL4JRFgycUOQyiDa?dl=0)
Also SabVoton Motor Controller V2.0 ( with bluetooth ) Vers. 1.0.0.0
also beim ziehen des USB-Kabels passiert ja was …die TX-LED leuchtet langsamer .
von daher gehe ich davon aus das die verbindung irgendwie steht von seitens des computers.
Ich könnte dir ja pic`s schicken …aber wohin ?
Hallo
Ein schönes projeckt von dir.
Ich bin dabei mir ein Ähnliches Bike zu bauen.
Deine Schlüsselschalter Lösung werde ich nachbauen.
Kannst du eine Übersicht erstellen welches arduino board du verwendet hast, und mit welchen Komtonenten du sie wie verschaltet sind?
Ich kann dir gerne ein paar bilder von meinem bike dir zusenden.
Es steht ja alles im Blog…du musst dir die Mühe schon selber machen die relevanten Details zu suchen. Die Verschaltung ist so: Gasgriff->CA-Arduino->RC-Glied->Controller
Hab auch en sabvoton und 72 Volt 3000 Watt eigentlich läuft er aber bei voll gas wird er wieder langsamer!? Wo ran kann das liegen
Ich würde mir mal diesen link anschauen: https://doc.ingeniamc.com/wiki/motion-wiki/why-sometimes-i-can-t-reach-100-motor-torque-when-is-already-turning das erklärt eigentlich das Problem. Dazu muss auch das Verhältnis zwischen Phasenstrom und Batteriestrom stimmen.
Gruss
Jetzt weiß ich glaub woran es gelegen hat der deutsche Händler hat mir einen sabvoton svcm 48060 im set mit einem 3000 Watt Motor verkauft der nur 1,5 kW Motoren unterstützt https://e-mon-shop.de/product_info.php?products_id=181 leider die Garantie verpasst nach Beschwerde und einsenden des systems mit Akku und Motor und der bitte es funktionstüchtig zu machen hat er mir einen uneingestellten svcm 96080 abgedreht der meiner recherche nach auch nur max. 2000 Watt unterstützt.
Wie hoch ist denn deine Akkuspannung (vollgeladen)?
Voll 84 Volt BMS bis 60 AMP oder sogar 80
Hmm, dann müsstest du aber locker über 2kW kommen. Ich hab den SVCM72100 @ 92.4V und komme mit einem ähnlichen Motor auf ca. 5kW Spitzenleistung. Mach mal einen Screenshot deiner Parameter im Sabvoton Controller tool.