Forum: Mikrocontroller und Digitale Elektronik gleichzeitig PWM für BLDC Motor + Auslesen eines fuelgauges mit I2C mit Energia


von Ferhat Yaman (Gast)


Lesenswert?

Hallo,
kurze Erklärung des Projekts:
Hardware: - Tiva C Board (tm4c1294xl)
          - Lipo Akku (3 Zellen, 11,1V, 2200mAh)
          - Bürstenloser DC Motor inkl. Regler (50hz)
          - BQ34Z100EVM fuel gauge (ladezustandsmesser mit I2C)

Software: Energia (wie Adruino)

Ich muss mit dem Tiva C Board eine PWM laufen lassen um den Motor zu 
betreiben. Gleichzeitig muss ich mit dem Board den Ladezustandsmesser 
über I2C auslesen.

Im Prinzip hab ich den Code fertig. Die PWM alleine läuft und der Motor 
beschleunigt. Das Auslesen allein funktioniert auch sehr gut.

Ich muss jetzt aber dafür sorgen dass die PWM ständig läuft und 
gleichzeitig alle paar Sekunden der Ladezustandsmesser ausgelesen wird.

Leider klappt das nicht, der Motor hört auf sich zu bewegen sobald ein 
Befehl zum Ablesen kommt.

Hat jemand eine Idee wie ich das machen könnte?
Falls ich irgendwelche relevanten Infos vergessen habe, entschuldige ich 
mich jetzt schon und werden nachgereicht sobald ich darauf aufmerksam 
gemacht wurde.

Danke

LG
Yaman

von where is it? (Gast)


Lesenswert?

Etwas vergessen? Ja, wo ist der Code???

von Joe (Gast)


Lesenswert?

Das kann man schon machen.

Melde dich mal richtig an, damit man dir eine PM schicken kann.

Joe

von Ferhat Y. (fyaman66)


Lesenswert?

Hallo bin bereits eingeloggt und der Code im Anschluss:

#include<Wire.h>

#define BQ34Z100 0x55    // eine fixe Adresse für I2C Datenblatt(Db) S28 
- 1010101

unsigned int soc, voltage, empty_time, full_Cap, rem_Cap;
unsigned int packcfg, descap, flag, nomavailcap, emptypower, 
average_pow, chemid;

int average_curr, inst_curr;

float batt_temp;
int motorPin = PF_2;

uint8_t flashbytes[32] = {0};

void setup() {

 pinMode(motorPin, OUTPUT);
   Serial.begin(9600);
  Wire.begin();
}

void loop() {
 noInterrupts();
 analogWrite(motorPin, HIGH);
 delayMicroseconds(1100);

 analogWrite(motorPin, LOW);
 delayMicroseconds(18900);

 interrupts();
 readInstantCurrent();
  Serial.print("Instantaneous Current: ");
  Serial.print(inst_curr);
  Serial.println(" mA");

  readTimetoEmpty();
  Serial.print("Time to Empty: ");
  Serial.print(empty_time);
  Serial.println(" min");

  getTemp();
  Serial.print("Battery Temperature: ");
  Serial.print(batt_temp / 10);
  Serial.println(" °C");

  getSOC();
  Serial.print("State of Charge: ");
  Serial.print(soc);
  Serial.println(" %");

  getVoltage();
  Serial.print("Battery Pack Voltage: ");
  Serial.print(voltage);
  Serial.println(" mV");

  getCapacity();
  Serial.print("Full Charge Capacity: ");
  Serial.print(full_Cap);
  Serial.println(" mAh");

  getRemaining();
  Serial.print("Remaining Capacity: ");
  Serial.print(rem_Cap);
  Serial.println(" mAh");

  getAverageCurrent();
  Serial.print("Average Current: ");
  Serial.print(average_curr);
  Serial.println(" mA\n");

  getPackCfg();
  Serial.print("Pack Configuration Register: ");
  Serial.println(packcfg, HEX);

  getChemID();
  Serial.print("Chemical ID: ");
  Serial.println(chemid);

  getDesCap();
  Serial.print("Design Capacity: ");
  Serial.print(descap);
  Serial.println(" mAh\n");

  getFlags();
  Serial.print("Flags: ");
  Serial.println(flag, HEX);
  Serial.print("\n\n\n");
}


uint32_t Read(int add, uint8_t length) {
    uint32_t returnVal = 0;

    for (int i = 0; i < length; i++) {
        Wire.beginTransmission(BQ34Z100);    // 0x55
        Wire.write(add + i);
        Wire.endTransmission();
        Wire.requestFrom(BQ34Z100, 1);
        returnVal = returnVal + (Wire.read() << (8 * i));
    }
    return returnVal;
}

int readControl(uint8_t add,uint8_t add2) {
    Wire.beginTransmission(BQ34Z100);
    Wire.write(add2);        // Subcommand part1
    Wire.write(add);        // Subcommand part2
    Wire.write(0x00);        // Subcommand wird vom Control() 
bereitgestellt
    Wire.endTransmission();

    Wire.beginTransmission(BQ34Z100);
    Wire.write(0x00);        // Control() wird ausgelesen
    Wire.endTransmission();
    Wire.requestFrom(BQ34Z100, 2);  // 2byte Daten werden verlangt
    int16_t temp = Wire.read();
    temp = temp | (Wire.read() << 8);
    return temp;
}

uint32_t getChemID() {
  return chemid = readControl(0x08, 0x00);      // Chemical ID
}

uint32_t readNomAvailCap() {
  return nomavailcap = Read(0x14, 2);          // Nominal Available 
Capacity
}

int32_t readInstantCurrent() {
  return inst_curr = Read(0x10, 2);      // momentaner Strom
}

uint32_t getAveragePower() {
  return average_pow = Read(0x26, 2);          // durchschnittliche 
Leistung
}

uint32_t readEmptyPower() {
  return emptypower = Read(0x28, 2);          // Zeit bis Akku Leer ist 
mit konstanter Leistung
}

uint32_t getPackCfg() {
  return packcfg = Read(0x3a, 2);            // Pack Configuration 
Register
}

uint32_t getDesCap() {
  return descap = Read(0x3c, 2);            // Akku Kapazität
}

uint32_t readTimetoEmpty() {
  return empty_time = Read(0x18, 2);          // Zeit bis Akku Leer ist 
mit der momentanen Last
}

uint32_t getTemp() {
  return batt_temp = Read(0x0c, 2) - 2731;       // Temperatur in 
Celsius
}

uint32_t getSOC() {
  return soc = Read(0x02, 1) ;             // State of Charge
}

uint32_t getVoltage() {
    return voltage = Read(0x08, 2) ;           // aktuelle Spannung
}

uint32_t getCapacity() {
  return full_Cap = Read(0x06, 2) ;           // maximale Akkukapazität
}

uint32_t getRemaining() {
  return rem_Cap = Read(0x04, 2) ;           // verbleibende 
Akkukapazität
}

int32_t getAverageCurrent() {
   return  average_curr = Read(0x0a, 2) ;         // durchschnittlicher 
Stromverbrauch
}

uint32_t getFlags() {
  return flag = Read(0x0E, 2);        // Flags
}

von where is it? (Gast)


Lesenswert?

Ferhat Y. schrieb:
> analogWrite(motorPin, HIGH);
>  delayMicroseconds(1100);
>
>  analogWrite(motorPin, LOW);
>  delayMicroseconds(18900);

Welche Werte haben 'HIGH' und 'LOW'? Wenn hinter 'LOW' eine 0 steht ...

von Jim M. (turboj)


Lesenswert?

Das geht so nicht. Das PWM Signal muss ein Hardware Timer oder 
mindestens ein Interrupt erzeugen, denn die ganzen Serial.printf() 
dauern viel länger als eine PWM periode. Bei 9600 Baud braucht ein Byte 
eine Millisekunde...

von where is it? (Gast)


Lesenswert?

Jim M. schrieb:
> Das geht so nicht.

Doch, prinzipiell schon:
http://energia.nu/Tutorial_Fade.html

von Ferhat Y. (fyaman66)


Lesenswert?

where is it? schrieb:
> Ferhat Y. schrieb:
>> analogWrite(motorPin, HIGH);
>>  delayMicroseconds(1100);
>>
>>  analogWrite(motorPin, LOW);
>>  delayMicroseconds(18900);
>
> Welche Werte haben 'HIGH' und 'LOW'? Wenn hinter 'LOW' eine 0 steht ...

Hallo,
HIGH = 5 Volt
LOW = 0 Volt

Ich glaube Jim hat recht, es muss eine Möglichkeit geben eine PWM zu 
erzeugen ohne die CPU zu belasten, also ohne delays.

Kurze Erklärung meiner PWM:
Die delays entsprechen gesamt 20 mikrosekunden. Da ich den Motor mit 
50Hz steuern muss: 1/50 = 20us

beim ersten delay von 1ms und zweiten delay von 19ms ist der Motor im 
Bremszustand.
Die Höchstgeschwindigkeit erreicht es wenn der erste delay auf 2ms und 
der zweite delay auf 18ms eingestellt wird.

Also Periode meiner PWM = 20us
Dutycycle = zwischen 5 - 10% für die Geschwindigkeit

Hat jemand eine Idee wie ich das ohne delays machen könnte?

LG
Yaman

: Bearbeitet durch User
von Ferhat Y. (fyaman66)


Lesenswert?

Hallo,

Danke an alle, ich habe die Lösung gefunden

Das hat bei mir funktioniert:

#include <wiring_analog.c>



void setup() {

     pinMode(PL_4, OUTPUT);

     PWMWrite(PL_4,1000,50,50);
// PWMWrite(PINnumber, number of steps, dutycycle, frequency)

}

von where is it? (Gast)


Lesenswert?

Danke für die Rückmeldung.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.