PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kompass-Modul Hdmm01 für den Rp6



Morpheus1997
03.03.2012, 17:53
Hey, Leute!
Ich habe mir vor einigen Tagen das Kompass-Modul Hdmm01 von Pollin gekauft, habe es angelötet und sitze nun schon den ganzen Tag daran, es zu programmieren,d.h., dass er die Grad-zahl angeben soll, so wie in Dirks Beispiel (siehe unterer Link), was allerdings bisher ohne Erfolg lief.
Erst habe ich versucht, Dieses Beispiel in C umzuschreiben: http://www.mtahlers.de/index.php/elektronik/sensoren/mmc2120mg
... was sich allerdings als äußerst kompliziert herausstellte, da ich bislang nur über wenige Bascom-Kenntnisse verfüge.
Nun bin ich dabei, das Beispiel von Dirk für den Cmps03 umzuschreiben: https://www.roboternetz.de/community/threads/30830-RP6-Beispiel-Devantech-CMPS03
Allerdings war mir nicht bewusst, dass die beiden Kompässe sehr unterschiedlich arbeiten, was sich schon beim einstellen der I²C Adresse gezeigt hat:
Laut dem Datenblatt ist die I²C-Adresse des Moduls &h60, doch wenn ich es nun definieren will, kommt die Fehlermeldung
error: invalid suffix "h" on integer constant :-(
Wieso wird die Adresse denn nicht angenommen? Ich weiß einfach nicht mehr weiter...
Es wäre nett, wenn ihr mir helfen könntet, da meine Kenntnisse vom I²C Bus-System und von "C" hier ihre Grenzen erreichen. Vielleicht hat ja jemand schon mal Erfahrungen mit diesem Kompass und dem Rp6 gemacht.
Liebe Grüße, Marcel

Berghuhn
03.03.2012, 18:11
Hallo,
das Hexadezimalsystem geht nicht bis h. Es geht von 0-9 und von a-f siehe: http://de.wikipedia.org/wiki/Hexadezimalsystem.
Das erklärt deinen Error, da dies keine gültige Adresse ist. Bist du sicher, dass das die richtige Adresse ist?

MfG,
Berghuhn

Morpheus1997
03.03.2012, 18:18
hm... also lt. dem Datenblatt (siehe http://www.pollin.de/shop/downloads/D810164D.PDF) lauetet die Adresse "Zitat HDMM01 ADDRESS=60H", seite 6
http://www.mtahlers.de/index.php/elektronik/sensoren/mmc2120mg : hier hat malthy (https://www.roboternetz.de/community/members/1745-malthy) ebenfalls dieselbe Adresse genommen, allerdings in Bascom.
edit: allerdings steht etwas weiter oben im Datenblatt eine etwas andere Slave-Adresse: 0110xx0, allerdings kommt dann wieder der selbe Error, nur eben auf die Suffix 110xx angepasst.

Dirk
03.03.2012, 22:01
@Morpheus1997:
Die Adresse 60H muss in GCC als 0x60 angegeben werden.

Morpheus1997
04.03.2012, 21:16
Hallo,
hm.. okay.. das bringt mich wenigstens schon mal einen schritt weiter. Allerdings hab ich nun das Beispielprogramm des Cmps03 mal wie folgt umgeschrieben:

/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - ROBOT BASE EXAMPLES
* ************************************************** **************************
* Example: I2C Master - Hdmm01 Rp6
* Author(s): M.Hunfeld
* ************************************************** **************************
* Description:
*
* This Example shows how to use the compass module Hdmm01
* with RP6Library.
*
* ************************************************** **************************
*/

/************************************************** ***************************/
// Includes:

#include "RP6RobotBaseLib.h"


// IMPORTANT:

#include "RP6I2CmasterTWI.h" // Include the I²C-Bus Slave Library


/************************************************** ***************************/
// I2C Event handlers:

/**
* This function gets called automatically if there was an I2C Error like
* the slave sent a "not acknowledge" (NACK, error codes e.g. 0x20 or 0x30).
* The most common mistakes are:
* - using the wrong address for the slave
* - slave not active or not connected to the I2C-Bus
* - too fast requests for a slower slave
* Be sure to check this if you get I2C errors!
*/
void I2C_transmissionError(uint8_t errorState)
{
writeString_P("\nI2C ERROR --> TWI STATE IS: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}

/************************************************** ***************************/


#define CMPS 0x60//Die Adresse des Hdmm01 Moduls
#define Read 0x61//Die Adresse des Hdmm01 Moduls zum Lesen
#define MEASURE_16_BIT 0x00//Die Register-Adresse



uint16_t readCMPS(uint8_t datareg)
{uint16_t result = 0xffff; uint8_t results[3];
I2CTWI_transmitByte(CMPS, datareg);
if (datareg == MEASURE_16_BIT) {
I2CTWI_readBytes(Read, results, 2);
result = (results[0] << 8) + results[1];
}
else {
result = I2CTWI_readByte(Read);
}
return result;
}


void task_CMPS(void)
{uint16_t degrees;
if (getStopwatch1() > 500) {
degrees = readCMPS(MEASURE_16_BIT);
writeString_P("Richtung: ");
writeIntegerLength((degrees / 10), DEC, 3);
writeChar('.');
writeIntegerLength(degrees, DEC, 1);
writeString_P(" Grad\n");
setStopwatch1(0);
}
}


/************************************************** ***************************/
// Main - The program starts here:

int main(void)
{
initRobotBase();

I2CTWI_initMaster(100); // Initialize the TWI Module for Master operation
// with 100kHz SCL Frequency

// Register the event handlers:
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);



powerON();

startStopwatch1();

while(true)
{
task_I2CTWI();
task_RP6System();
task_CMPS();

}
return 0;
}



Allerdings, das Ergebnis:



I2C ERROR --> TWI STATE IS: 0x20

I2C ERROR --> TWI STATE IS: 0x48
Richtung: 000.0 Grad

I2C ERROR --> TWI STATE IS: 0x20

I2C ERROR --> TWI STATE IS: 0x48
Richtung: 000.0 Grad


Es wird wahrscheinlich daran liegen, dass es bei dem Hdmm01 Modul nur ein Register gibt, welches man allerdings manipulieren muss. Malthy hat es in Bascom so gelöst:
072.' sensor adressieren (schreiben)
073.I2cwbyte Cmp_w
074.' register adressieren
075.I2cwbyte &H00
076.'
077.' register manipulieren -> reset coil
078.I2cwbyte &B00000100

Doch wie realisiert man dies in "C", für die Rp6 Lib tauglich?

Liebe Grüße Marcel

Dirk
04.03.2012, 22:44
Hi Marcel,

das Modul CMPS03 wird völlig anders ausgelesen als der HDMM01. Daher kannst du mein Programm nicht 1:1 nehmen.

Ich habe den HDMM01 nicht selbst. Du kannst folgendes Testprogramm mal als Anfang für eigene Experimente nehmen:

/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - ROBOT BASE EXAMPLES
* ************************************************** **************************
* Example: I2C Master - HDMM01
* Author(s): Dirk
* ************************************************** **************************
* Description:
*
* This Example shows how to use the compass module HDMM01
* with RP6Library.
*
* ************************************************** **************************
*/
/************************************************** ***************************/
// Includes:
#include "RP6RobotBaseLib.h"

// IMPORTANT:
#include "RP6I2CmasterTWI.h" // Include the I²C-Bus Slave Library

/************************************************** ***************************/
// I2C Event handlers:
/**
* This function gets called automatically if there was an I2C Error like
* the slave sent a "not acknowledge" (NACK, error codes e.g. 0x20 or 0x30).
* The most common mistakes are:
* - using the wrong address for the slave
* - slave not active or not connected to the I2C-Bus
* - too fast requests for a slower slave
* Be sure to check this if you get I2C errors!
*/
void I2C_transmissionError(uint8_t errorState)
{
writeString_P("\nI2C ERROR --> TWI STATE IS: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}
/************************************************** ***************************/
/**
* Write a long number (with specified base) to the UART.
*
* Example:
*
* // Write a hexadecimal number to the UART:
* writeLong(0xAACC,16);
* // Instead of 16 you can also write "HEX" as this is defined in the
* // RP6uart.h :
* writeLong(0xAACC, HEX);
* // Other Formats:
* writeLong(1024,DEC); // Decimal
* writeLong(044,OCT); // Octal
* writeLong(0b11010111,BIN); // Binary
*/
void writeLong(int32_t number, uint8_t base)
{char buffer[33];
ltoa(number, &buffer[0], base);
writeString(&buffer[0]);
}
/************************************************** ***************************/
// The I2C slave address of the compass module HDMM01 is 0x60:
#define HDMM01_ADR 0x60
// HDMM01 Data Register:
#define DATA_REG 0
// HDMM01 Commands:
#define SET_COIL 0b00000010
#define RESET_COIL 0b00000100
#define MEASURE 0b00000001
uint8_t results[5];
/**
* READ HDMM01 DATA REGISTER
*
* This function reads the data register of the HDMM01.
*
*/
void readHDMM01(void)
{
I2CTWI_transmit2Bytes(HDMM01_ADR, DATA_REG, SET_COIL);
mSleep(1);
I2CTWI_transmit2Bytes(HDMM01_ADR, DATA_REG, RESET_COIL);
mSleep(5);
I2CTWI_transmit2Bytes(HDMM01_ADR, DATA_REG, MEASURE);
mSleep(5);
I2CTWI_transmitByte(HDMM01_ADR, DATA_REG);
// Hier sollte eigentlich kein Stop sein ...
I2CTWI_readBytes(HDMM01_ADR, results, 5);
return;
}
/**
* HDMM01 TASK
*
* This is the HDMM01 task.
*
*/
void task_HDMM01(void)
{uint16_t X, Y;
if (getStopwatch1() > 500) {
readHDMM01();
results[1] = results[1] & 0b00001111;
results[3] = results[3] & 0b00001111;
X = results[1] * 256;
X = X + results[2];
Y = results[3] * 256;
Y = Y + results[4];
writeString_P("XY: ");
writeLong(X, DEC);
writeChar(' ');
writeLong(Y, DEC);
writeString_P(" \n");
setStopwatch1(0);
}
}
/************************************************** ***************************/
// Main - The program starts here:
int main(void)
{
initRobotBase();

I2CTWI_initMaster(100); // Initialize the TWI Module for Master operation
// with 100kHz SCL Frequency

// Register the event handlers:
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);
setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);

powerON();
startStopwatch1();

while(true)
{
task_HDMM01();
task_I2CTWI();
task_RP6System();
}
return 0;
}
/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.0beta (initial release) 04.03.2012 by Dirk
*
* ************************************************** **************************
*/
/************************************************** ***************************/

Ein Problem bei der Lesefunktion ist, dass an einer Stelle (siehe Kommentar) eigentlich kein Stop gesendet werden darf. Das macht aber die RP6 Library.
Aber: Probier das doch erst einmal.

Morpheus1997
05.03.2012, 17:16
Hey Dirk,
vielen Dank schon mal für deine Bemühungen, aber leider ist bei diesem Programm das gleiche Problem: wieder dieser I2C ERROR...
Lg Marcel

teamohnename
05.03.2012, 19:01
Hey Morpheus1997,
vermutlich wirst Du nicht drumrumkommen, eine andere I²C Library, z.B. die von Peter Fleury, zu verwenden. Wir hatten mit einem anderen Sensor auch das Problem (https://www.roboternetz.de/community/threads/56861-Frage-zu-RP6-I2C-Library-Funktionen-der-Lib-von-Peter-Fleury), dass die RP6Lib automatisch I²C Stops, Restarts oder Starts sendet, die für den Sensor nicht gesendet werden dürfen.
Natürlich kannst Du gerne noch weiter versuchen, vielleicht schaffst Du es ja doch noch. Vermutlich wirst Du aber schneller mit einer anderen Library Erfolg haben.
Viele Grüße
teamohnename

hsc123
09.08.2012, 18:33
Hey Morpheus1997

nimm mal die aktuellste Lib vom rp6. Damit funktioniert es einwandfrei.

Die funktion zum einlesen des hdmm01 sieht dann einfach so aus :

#define hdmm01_address 0x60

void rbh_i2c_hdmm01( void )
{

unsigned char buf[ 5 ];


I2CTWI_transmit2Bytes( hdmm01_address, 0x00, 0b00000001 ); // take measurement
mSleep( 10 );
I2CTWI_transmitByte( hdmm01_address, 0x00 );
I2CTWI_readBytes( hdmm01_address, buf, 5 ); // read control - register + x , y - values

writeString_P("\nrbh_i2c_hdmm01: 0x");
writeInteger( buf[ 0 ], HEX);
writeChar(' ');
writeInteger( buf[ 1 ], HEX);
writeChar(' ');
writeInteger( buf[ 2 ], HEX);
writeChar(' ');
writeInteger( buf[ 3 ], HEX);
writeChar(' ');
writeInteger( buf[ 4], HEX);
writeChar(' ');
}

Viele Grüße
HSC123