I²C-Testschaltungen und Beispiele

Modelle zum Nachbauen oder wo gibt es etwas interessantes oder Projekte?

Moderator: Moderatoren

Benutzeravatar
Sebi
Administrator
Administrator
Beiträge: 1946
Registriert: 11. Jan 2008 14:28
Wohnort: Aub
Kontaktdaten:

I²C-Testschaltungen und Beispiele

Beitragvon Sebi » 24. Jan 2010 17:29

Das hier soll eine Sammlung für I²C Testschaltungen mit verschieden ICs werden.
Ich fang mal an:
PCF8574P mit 8 LEDs
Steckerbelegung:
Pin 1-3==A0-2
Pin 4-7== P0-3
Pin 8== GND/-
Pin 9-12==P4-7
Pin 13== INT
Pin 14== SCL
Pin 15== SDA
Pin 16==Vdd/+5V
Mit A0-2 wird die I²C Adresse festglegt. Hier 0x40. Die einzelnen Ports werden je nach gewünschter I²C Adresse an GND oder Vdd angeschlossen.

Px sind seind die I/O Ports. (Eingang (z.B. Taster) und Ausgang(z.B. LED)).
SCL und SDA sind die Pins für die I²C Kommunikation. Sie benötigen noch einen Pull-Up mit 82k (beim NXT).

INT wird vom PCF8574 kurz auf 1 geschaltet, wenn ein angeschlossenere Taster gedrückt wird. (Wird dann an ADA(Pin1) angeschlossen)
So muss man nicht die ganze Zeit über I²C fragen, ob ein Taster gedrückt ist(verbraucht Rechenleistung). Sondern man wartet, bis der "Tastsenor" gedrückt ist, und liest dann per I²C die Ports aus.

Die LEDs müssen mit Kathode an Px angeschlossen werden. Mit Anode an Px leuchten sie nicht so hell, und die Einzel-Ausgangsteuerung (Programm) funktionert nicht richtig. Dementsprechend ist die LED dann bei 1 aus, und bei 0 an.
Wenn man die volle Helligkeit haben will, und die LEDs mit 1=an bzw. 0=aus steuern will, muss man Transistoren benutzen.

Schaltplan:
Bild
R1 und R2 haben 82k. Für R3-10 muss man selber wissen wie hell die LEDs sein sollen. (Standard mäßig benutzt man bei 5V 220Ohm. Aber Ich würde lieber größer Widerstände (z.B. 470Ohm) nehmen. Sonst stirbt er noch den Hitzetod.) Wenn man eine größere Last schalten will, sollte man einen Transistor benutzen.
Der PFC8574 "verträgt" (glaube ich) max. 100mA.(An allen Ausgängen zusammen.)
Aufbau auf Steckbaord:
AUFBAU
Falls es jemand schafft, die Drahtbrücken besser zu verlegen, bitte melden.
Programm:
Ich empfehle den PCF8574 Treiber von Adam Mokanszki. Man muss aber die I²C Adresse zu 0x40 ändern.
Programm für 8x Lauflicht:

Code: Alles auswählen

#include "pcf8574llb.nxc"

task main()
{
    int port=1;
    bool richtung=true;
    SetSensorLowspeed(S1);
    WritePorts(0xFF); //Alle Ports auf 1(+) setzen.
    Wait(100);
    while(true)
    {
        DeletePort(port); //Wechselt Wert 1(+)->0(-)
        Wait(500);
        WritePort(port); //Schreibt 1(+)
        if(richtung==true)
        {
           port++;
        }
        else
        {
           port-=1;
        }
        if(port==8)
        {
           richtung=false;
        }
        if(port==1)
        {
           richtung=true;
        }
    }
}


pcf8574llb.nxc

Code: Alles auswählen


/*************************************************************/
/*                                                           */
/*                     PCF8574Driver for NXC                 */
/*                                                           */
/*                 Programmed by: Adam Mokanszki             */
/*                                                           */
/*                 University of Debrecen Hungary            */
/*                                                           */
/*                            ENJOY! :)                      */
/*                                                           */
/*************************************************************/
#ifndef _PCF8574_
#define _PCF8574_

#define  PCF8574ID  0x40    //The address of your PCF8574- Hier muss 0x40 hin.
#define  PCF8574Port  S1   //This is the port on the NXT where the device is connected

void WritePort(char input);  //Writing a single port the input is the port number 1-8
void DeletePort(char input); //Deleting a single port the input is the port number 1-8
void WritePorts(byte input); //Writing all ports with one byte
int ReadPort(char input);    //Reading a single port the input is the port number 1-8 returning with a logical value in integer: 0,1
int ReadPorts();             //Reading all ports returning with one byte
                             //That's all what you need to know about this file

void WritePort(char input){

    byte cnt = 0x02;
    byte I2CMsg[];
    byte inbuf[];
    byte Address = PCF8574ID;
    byte nByteReady = 0;
    int  result = -1;
    int loop;
   
    ArrayBuild(I2CMsg, Address);

    Wait(8);

    while (loop == STAT_COMM_PENDING) {

          loop = I2CStatus(PCF8574Port, nByteReady);

    }

    if (I2CBytes(PCF8574Port, I2CMsg, cnt, inbuf)) {

        result = inbuf[1];

    }

    byte Command = result | (1<<(input-1));

    ArrayBuild(I2CMsg, Address, Command);

    while (loop == STAT_COMM_PENDING) {
        loop = I2CStatus(PCF8574Port, nByteReady);
    }

    I2CWrite(S1, 1, I2CMsg);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }
}

void DeletePort(char input){

    byte cnt = 0x02;
    byte I2CMsg[];
    byte inbuf[];
    byte Address = PCF8574ID;
    byte nByteReady = 0;
    int  result = -1;
    int loop;

    ArrayBuild(I2CMsg, Address);

    Wait(8);

    while (loop == STAT_COMM_PENDING) {

          loop = I2CStatus(PCF8574Port, nByteReady);

    }

    if (I2CBytes(PCF8574Port, I2CMsg, cnt, inbuf)) {

        result = inbuf[1];

    }

    byte Command = result ^ (1<<(input-1));

    ArrayBuild(I2CMsg, Address, Command);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }

    I2CWrite(S1, 1, I2CMsg);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }

}

void WritePorts(byte input){

    byte I2CMsg[];
    byte Address = PCF8574ID;
    byte Command = input;
    byte nByteReady = 0;
    int loop;
   
    ArrayBuild(I2CMsg, Address, Command);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }

    I2CWrite(S1, 1, I2CMsg);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }
}

int ReadPort(char input){

    byte cnt = 0x02;
    byte I2CMsg[];
    byte inbuf[];
    byte Address = PCF8574ID;
    byte nByteReady = 0;
    int  result = -1;
    int loop;

    ArrayBuild(I2CMsg, Address);
    Wait(8);
    while (loop == STAT_COMM_PENDING) {

          loop = I2CStatus(PCF8574Port, nByteReady);

    }

    if (I2CBytes(PCF8574Port, I2CMsg, cnt, inbuf)) {

        result = inbuf[1];

    }

    if( result == (result | (1<<input-1)) ){

       result = 1;

    }
    else{

       result = 0;

    }
   
    if(result==-1){

     TextOut(0, LCD_LINE7, "Error: Check the");
     TextOut(0, LCD_LINE8, "   connection!");
     Wait(500);
     ClearScreen();
    }
    return result;
}

int ReadPorts(){

    byte cnt = 0x02;
    byte I2CMsg[];
    byte inbuf[];
    byte Address = PCF8574ID;
    byte nByteReady = 0;
    int  result = -1;
    int loop;

    ArrayBuild(I2CMsg, Address);

    Wait(8);

    while (loop == STAT_COMM_PENDING) {

          loop = I2CStatus(PCF8574Port, nByteReady);

    }

    if (I2CBytes(PCF8574Port, I2CMsg, cnt, inbuf)) {

        result = inbuf[1];

    }
    if(result==-1){

     TextOut(0, LCD_LINE7, "Error: Check the");
     TextOut(0, LCD_LINE8, "   connection!");
     Wait(500);
     ClearScreen();
    }
    return result;
}
#endif
Zuletzt geändert von Sebi am 17. Apr 2010 18:51, insgesamt 16-mal geändert.

Benutzeravatar
Bertolego
Moderator
Moderator
Beiträge: 773
Registriert: 16. Mai 2006 18:27
Wohnort: NRW

Beitragvon Bertolego » 24. Jan 2010 21:16

Ist eine coole Idee I²C Schaltungen für den NXT hier vorzustellen!
Damit wird vielleicht der Basteldrang noch mehr vorangetrieben! :D
Wenn es mehr Schaltungen werden, dann können wir eine eigene Rubrik dafür aufmachen!

PCF8574 Erweiterung:
bilder/details.php?image_id=173
Bild

bilder/details.php?image_id=174
Bild

I²C RAM
viewtopic.php?t=4915

Was können wir sonst noch mit dem I²C -Bus machen und realisieren?
Motorporterweiterung, SensorMux?!

Zeigt her eure I²C Ideen und Projekte! :D

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5402
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Mighty Board

Beitragvon HaWe » 24. Jan 2010 22:45

ich habe hier einen RobotC-Treiber für einen 8xSharp Sensor-Mux.

mightyboard-schematic.png
mightyboard-schematic.png (48.95 KiB) 10176 mal betrachtet


http://botbench.com/blog/2009/03/02/sharp-ir-mux-board/

Arbeitet mit einem MCP23008, einem MAX127 und einem ULN2803A


I2C.h

Code: Alles auswählen

#ifndef __I2C_H__
#define __I2C_H__

#define MAX_ARR_SIZE 16
typedef byte byte_array[MAX_ARR_SIZE];

void clearI2CBus(tSensors _link);
void waitForI2CBus(tSensors _link);
void writeI2Cvalue(tSensors _link, byte_array &_data, int _replylen);
void readI2Cvalue(tSensors _link, byte_array &_data, int _replylen);

/*
  =============================================================================
  Clear the I2C bus before we send new data.

 */
void clearI2CBus(tSensors _link) {
  ubyte _tmp = 0;
  while (nI2CBytesReady[_link] > 0)
    readI2CReply(_link, _tmp, 1);
}

/*
  =============================================================================
  We wait for the I2C bus to be ready for the next message or emit a
  loud annoying buzz sound if there's an error.
  Taken from RobotC example code and modified.

 */
void waitForI2CBus(tSensors _link)
{
   byte _tmp = 0;
   TI2CStatus nStatus;

   while (true)
   {
      nStatus = nI2CStatus[_link];
      switch (nStatus)
      {
      case NO_ERR:
      return;

      case STAT_COMM_PENDING:
         break;

      case ERR_COMM_BUS_ERR:
         PlaySound(soundLowBuzz);
         while (bSoundActive) {}
         // clear out any old buffers.
      clearI2CBus(_link);
         return;
      }
   }
}

void writeI2Cvalue(tSensors _link, byte_array &_data, int _replylen) {
  clearI2CBus(_link);
  waitForI2CBus(_link);
  sendI2CMsg(_link, _data[0], _replylen);
  waitForI2CBus(_link);
}

void readI2Cvalue(tSensors _link, byte_array &_data, int _replylen) {
  readI2CReply(_link, _data[0], _replylen);
  waitForI2CBus(_link);
}


#endif // __I2C_H__




MAX127.h

Code: Alles auswählen

#ifndef __MAX127_H__
#define __MAX127_H__
/*
    MAXIM MAX126 ADC driver for ROBOTC
    Author: Xander Soldaat
    Date: 03 Sept 2008
    Version: 0.3
    Contact: mightor_at_gmail.com
    Usage:
    * int readMAX127(Sensor, I2C address (0-127), Channel (0-7));
      Returns the current analogue value as measured on the specified channel.

    Note:
    The article accompanying this code can be found here:
    http://mightor.wordpress.com/2008/07/19/maximum-conversion/

-
For more details about how the MAX127 works, please refer to the datasheet. A quick
reference can be found below.

Taken from the MAX127 Datasheet:

Table 1. Control-Byte Format
Bit 7 == MSB
| BIT 7 | BIT 6 | BIT 5 | BIT 4 | BIT 3 | BIT 2 | BIT 1 | BIT 0 |
| START | SEL 2 | SEL 1 | SEL 0 | RNG   | BIP   | PD1   | PD0   |

BIT     NAME    DESCRIPTION
7 (MSB) START   The logic "1" received after acknowledge of a write bit (R/W = 0)
                defines the beginning of the control byte.
6, 5, 4 SEL2,   These three bits select the desired "ON" channel (Table 2).
        SEL1,
        SEL0
3       RNG     Selects the full-scale input voltage range (Table 3).
2       BIP     Selects unipolar or bipolar conversion mode (Table 3).
1, 0    PD1,    These two bits select the power-down modes (Table 4).
        PD0

Table 2. Channel Selection
SEL2  SEL1  SEL0  CHANNEL
0     0     0     CH0
0     0     1     CH1
0     1     0     CH2
0     1     1     CH3
1     0     0     CH4
1     0     1     CH5
1     1     0     CH6
1     1     1     CH7

Table 3. Range and Polarity Selection
INPUT RANGE (V) RNG BIP   NEGATIVE FULL   ZERO        FULL SCALE (V)
                          SCALE (V)       SCALE (V)
MAX127
0 to 5          0   0     â€“               0           VREF x 1.2207
0 to 10         1   0     â€“               0           VREF x 2.4414
±5              0   1     -VREF x 1.2207  0           VREF x 1.2207
±10             1   1     -VREF x 2.4414  0           VREF x 2.4414

MAX128
0 to VREF/2     0   0     â€“               0           VREF/2
0 to VREF       1   0     â€“               0           VREF
±VREF/2         0   1     -VREF/2         0           VREF/2
±VREF           1   1     -VREF           0           VREF

Table 4. Power-Down and Clock Selection
PD1 PD0 MODE
0   X   Normal Operation (always on)
1   0   Standby Power-Down Mode (STBYPD)
1   1   Full Power-Down Mode (FULLPD)

*/

#ifndef __I2C_H__
#include "i2c.h"
#endif //__I2C_H__

#define MAX127_I2C_ADDR 0x50

int ubyteToInt(ubyte _byte);
int readMAX127(tSensors _link, byte _address, byte _channel);


// This function allows conversion of an unsigned byte to a signed int.
// This is a work-around for RobotC bug entry 222
// http://www.education.rec.ri.cmu.edu/tools/mantis/view.php?id=222
int ubyteToInt(ubyte _byte) {
   int _tmp = (_byte & 0x80) ? (_byte & 0x7F) + 0x80 : _byte;
   return _tmp;
}

// Returns the current analogue value as measured on the specified channel.
int readMAX127(tSensors _link, byte _address, byte _channel)
{
   byte _I2Crequest[3] =
   {
    2,                          // Message size
    _address,                   // I2C Address
    (1 << 7) + (_channel << 4)  // Control Byte:
  };                            //    start bit (7) + channel number bit-shifted into place

   byte _I2Creply[2] = {0, 0};   // I2C reply is 2 bytes
   int _chVal = 0;               // ADC channel value after bit shifting of reply

  // clear out any old buffers.
  clearI2CBus(_link);
   waitForI2CBus(_link);

   // Send our request for the value of the channel
  sendI2CMsg(_link, _I2Crequest[0], 2);
  waitForI2CBus(_link);

  // Read the 2 byte long reply into the array
  readI2CReply(_link, _I2Creply[0], 2);

  // Convert the bytes into ints
  // 1st byte contains bits 11-4 of the channel's value
  // 2nd byte contains bits 3-0 of the channel's value, followed by 4 0's
  // We'll need to shift the 1st byte left by 4 and the 2nd byte to the right by 4
  _chVal = (ubyteToInt(_I2Creply[0]) <<4>> 4);
  // _chVal = (_I2Creply[0] <<4>> 4);

  return _chVal;
}
#endif // __MAX127_H__



MCP23008.h

Code: Alles auswählen

#ifndef __MCP23008_H__
#define __MCP23008_H__
/*
    RobotC Microchip MCP23008 driver
    Author: Xander Soldaat
    Date: 09/09/2008
    Version: 0.2
    Contact: mightor_at_gmail.com
    Usage:
    * MCP23008WriteReg(Sensor, I2C Addr (0x00 - 0x7F), Register (0x00-0x0A), Data)
                                              Writes specified data to regiser
    * MCP23008ReadReg(Sensor, I2C Addr (0x00 - 0x7F), Register (0x00-0x0A))
                                              Reads specified regiser and returns data (byte)

    Note:

    THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 1.40 AND HIGHER.
*/
#ifndef __I2C_H__
#include "i2c.h"
#endif //__I2C_H__

// Registers
#define MCP_REG_IODIR   0x00    // I/O DIRECTION REGISTER
#define MCP_REG_IPOL    0x01    // INPUT POLARITY REGISTER
#define MCP_REG_GPINTEN 0x02    // INTERRUPT-ON-CHANGE CONTROL REGISTER
#define MCP_REG_DEFVAL  0x03    // DEFAULT COMPARE REGISTER FOR INTERRUPT-ONCHANGE
#define MCP_REG_INTCON  0x04    // INTERRUPT CONTROL REGISTER
#define MCP_REG_IOCON   0x05    // CONFIGURATION REGISTER
#define MCP_REG_GPPU    0x06    // PULL-UP RESISTOR CONFIGURATION REGISTER
#define MCP_REG_INTF    0x07    // INTERRUPT FLAG (INTF)REGISTER
#define MCP_REG_INTCAP  0x08    // INTERRUPT CAPTURE REGISTER
#define MCP_REG_GPIO    0x09    // PORT REGISTER
#define MCP_REG_OLAT    0x0A    // OUTPUT LATCH REGISTER

// Special bits in the IOCON register
#define MCP_BIT_INTPOL  1       // This bit sets the polarity of the INT output pin
#define MCP_BIT_ODR     2       // This bit configures the INT pin as an open-drain output
#define MCP_BIT_DISSLW  4       // Slew Rate control bit for SDA output
#define MCP_BIT_SREAD   5       // Sequential Operation mode bit

#define MCP_I2C_ADDR    0x40    // Default base address (A0-A2 tied to gnd)

void MCP23008SetupIO(tSensors _link, byte _addr, byte _mask, byte _pullup);
void MCP23008SetupIO(tSensors _link, byte _addr, byte _mask);
byte MCP23008ReadIO(tSensors _link, byte _addr, byte _mask);
byte MCP23008ReadIO(tSensors _link, byte _addr);
void MCP23008WriteIO(tSensors _link, byte _addr, byte _mask);

void MCP23008WriteReg(tSensors _link, byte _addr, byte _reg, byte _data);
byte MCP23008ReadReg(tSensors _link, byte _addr, byte _reg);

/*
  =============================================================================
  Write data to the device at the specified register

 */
void MCP23008WriteReg(tSensors _link, byte _addr, byte _reg, byte _data) {
   byte _I2CRequest[4] =
   {
    3,                // Message size
    _addr,            // I2C Address
    _reg,             // Register address
    _data             // Data to be sent
  };
  clearI2CBus(_link);
  waitForI2CBus(_link);
  sendI2CMsg(_link, _I2CRequest[0], 0);
  waitForI2CBus(_link);
}

/*
  =============================================================================
  Write data to the device at the specified register

 */
byte MCP23008ReadReg(tSensors _link, byte _addr, byte _reg) {
   byte _I2CRequest[3] =
   {
    2,                // Message size
    _addr,            // I2C Address
    _reg,             // Register address
  };
  byte _I2CReply[1];  // Reply of request

  clearI2CBus(_link);
  waitForI2CBus(_link);

   // Send our request to read the value of the register.
  sendI2CMsg(_link, _I2CRequest[0], 1);
  waitForI2CBus(_link);

  // Read the reply into the array
  readI2CReply(_link, _I2CReply[0], 1);
  waitForI2CBus(_link);

  return _I2CReply[0];
}

void MCP23008SetupIO(tSensors _link, byte _addr, byte _mask, byte _pullup) {
   MCP23008WriteReg(_link, _addr, MCP_REG_IODIR, _mask);
   MCP23008WriteReg(_link, _addr, MCP_REG_GPPU, _pullup);
}

void MCP23008SetupIO(tSensors _link, byte _addr, byte _mask) {
   MCP23008WriteReg(_link, _addr, MCP_REG_IODIR, _mask);
}

byte MCP23008ReadIO(tSensors _link, byte _addr, byte _mask) {
   return MCP23008ReadReg(_link, _addr, MCP_REG_GPIO) & _mask;
}

byte MCP23008ReadIO(tSensors _link, byte _addr) {
   return MCP23008ReadReg(_link, _addr, MCP_REG_GPIO);
}

void MCP23008WriteIO(tSensors _link, byte _addr, byte _mask) {
   MCP23008WriteReg(_link, _addr, MCP_REG_OLAT, _mask);
}

#endif // __MCP23008_H__




Mightyboard.h

Code: Alles auswählen

#ifndef __MIGHTYBOARD_H__
#define __MIGHTYBOARD_H__

#ifndef __MCP23008_H__
#include "mcp23008.h"
#endif

#ifndef __MAX127_H__
#include "max127.h"
#endif

tSensors _board = sensorNone;
byte _enabledSensors = 0;

void initBoard(tSensors _link);
void enableSensors(byte _mask);
void enableSensors(tSensors _link, byte _mask);
int readSensor(byte _channel);
int readSensor(byte _channel, byte _precision);
int readSensor(tSensors _link, byte _channel);
int readSensor(tSensors _link, byte _channel, byte _precision);


// Initialise the board and configure the sensor port it is attached to
void initBoard(tSensors _link) {
   _board = _link;
}

// Allows for sensors to be enabled and disabled according to the mask, 1 is on, 0 is off
void enableSensors(byte _mask) {
   _enabledSensors = _mask;
  MCP23008SetupIO(_board, MCP_I2C_ADDR, 0x0);
  MCP23008WriteIO(_board, MCP_I2C_ADDR, _mask);
}

void enableSensors(tSensors _link, byte _mask) {
   _enabledSensors = _mask;
  MCP23008SetupIO(_link, MCP_I2C_ADDR, 0x0);
  MCP23008WriteIO(_link, MCP_I2C_ADDR, _mask);
}

// Get the ADC value of the associated channel, return -1 of the sensor was not enabled.
int readSensor(byte _channel) {
  return readSensor(_board, _channel, 12);
}

int readSensor(byte _channel, byte _precision) {
  return readSensor(_board, _channel, _precision);
}

int readSensor(tSensors _link, byte _channel) {
   return readSensor(_link, _channel, 12);
}

int readSensor(tSensors _link, byte _channel, byte _precision) {
   if ((_enabledSensors >> _channel) & 1) {
     return readMAX127(_link, MAX127_I2C_ADDR, _channel) >> (12 - _precision);
   } else {
      return -1;
   }
}

#endif // __MIGHTYBOARD_H__



MightyboardDemo.h

Code: Alles auswählen

#pragma config(Sensor, S1,     MB,                  sensorI2CCustomFastSkipStates)
//*!Code automatically generated by 'ROBOTC' configuration wizard               !*//

#include "mightyboard.h"


task main() {
   int _counter = 0;
   int _sensorVal = 0;
   eraseDisplay();
   nxtDisplayString(2, "MightyBoard v1.0");
   nxtDisplayString(3, "Demo Program");
   PlaySound(soundFastUpwardTones);
  while (bSoundActive) {}
  PlaySound(soundDownwardTones);
  while (bSoundActive) {}

   // setup the link to the board
   // initBoard(MB);
   enableSensors(MB, 0xFF);

  eraseDisplay();
   while (true) {
    //eraseDisplay();
    for (_counter = 0; _counter < 8; _counter++) {
       _sensorVal = readSensor(MB, _counter);
       if (_sensorVal < 0) {
          PlaySound(soundException);
          wait1Msec(20000);
       }
       //nxtDisplayClearTextLine(_counter);
      nxtDisplayTextLine(_counter, "%2d: %4d", _counter+1, _sensorVal);
      wait1Msec(10);
    }
   }
}
Zuletzt geändert von HaWe am 11. Jun 2010 15:04, insgesamt 5-mal geändert.
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5402
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Beitragvon HaWe » 18. Feb 2010 12:43

@Bertolego:
wozu sind bei deinem Platinenlayout die blau-weißen Dipp-Schalter?
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
Bertolego
Moderator
Moderator
Beiträge: 773
Registriert: 16. Mai 2006 18:27
Wohnort: NRW

Beitragvon Bertolego » 18. Feb 2010 18:20

Mit den Dip-Schaltern werden die PortPins vom PCF8574 auf Masse (logisch 0) gelegt.
Bei einem offenen Schalter liegt der PortPin (über den Pull-Up Widerstand) auf Versorgungsspannung,
also somit logisch auf 1.

Je nach Befehl, kann der PCF8574 ein Byte an die PortPins ausgeben
(linker Teil der Schaltung mit den LEDs), oder eben den Zustand der PortPins als Byte einlesen!
(rechter Teil mit den Schaltern)

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5402
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Beitragvon HaWe » 18. Feb 2010 19:00

d.h. anstatt der blauen Schalter könnten dann Touch Sensoren angeschlossen werden?

und kann man mit dem Chip auch analoge Spannungen oder Widerstände messen (Sharp: IR Distanz-Sensor oder Lego: analoger passiver Sensor)?
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
Sebi
Administrator
Administrator
Beiträge: 1946
Registriert: 11. Jan 2008 14:28
Wohnort: Aub
Kontaktdaten:

Beitragvon Sebi » 18. Feb 2010 19:02

1. Ja
2. Nein. Nur log. 1 und 0
Ein PCF8591 hat aber 4 8bit Analog Inputs.
EDIT:
Du kannst aber (mit einem Transistor) die Analogen-Quellen auf Pin1 schalten.
Aber für Sharp Sensoren bräuchtest du noch einen zweiten Transistor...
(Falls du das Extreme NXT hast) Guck mal auf Seite 117

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5402
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Beitragvon HaWe » 21. Feb 2010 10:47

hier jetzt der Mightyboard 8x Sharp IR Sensor Mux mit NXC-Treiberprogramm:
<img src="http://inlinethumb15.webshots.com/42958/2249993540102874070S600x600Q85.jpg" width="300" height="400" alt="Mindstormsforum"> Bild
http://entertainment.webshots.com/photo/2214226090102874070CoBGUK


Code: Alles auswählen

#define MAX_ARR_SIZE 16

#define printf2v( _x, _y, _format1, _format2, _value1, _value2) { \
  string sval1 = FormatNum(_format1, _value1); \
  string sval2 = FormatNum(_format2, _value2); \
  string s =sval1+sval2; \
  TextOut(_x, _y, s); \
}


//===========================================================================
//  attached  NXC port in this example:  S1  (muss angepasst werden!)

byte MB_port=S1;

//===========================================================================


//===========================================================================
//  Clear the I2C bus before we send new data.

void clearI2CBus(byte port) {
  byte buf = 0; byte status;
  do {status=I2CRead(port, 1, buf);}
  while (status != NO_ERR);

}


void I2CWaitUntilReady(byte port) {
   byte status, byteReady=0;
   do {status = I2CStatus(port, byteReady);}
   while (status == STAT_COMM_PENDING);

}
//====================================





/*
    MAXIM MAX126 ADC driver for ROBOTC
    Author: Xander Soldaat
    Date: 03 Sept 2008
    Version: 0.3
    Contact: mightor_at_gmail.com
    Usage:
    * int readMAX127(Sensor, I2C address (0-127), Channel (0-7));
      Returns the current analogue value as measured on the specified channel.

    Note:
    The article accompanying this code can be found here:
    http://mightor.wordpress.com/2008/07/19/maximum-conversion/

-
For more details about how the MAX127 works, please refer to the datasheet. A quick
reference can be found below.

Taken from the MAX127 Datasheet:

Table 1. Control-Byte Format
Bit 7 == MSB
| BIT 7 | BIT 6 | BIT 5 | BIT 4 | BIT 3 | BIT 2 | BIT 1 | BIT 0 |
| START | SEL 2 | SEL 1 | SEL 0 | RNG   | BIP   | PD1   | PD0   |

BIT     NAME    DESCRIPTION
7 (MSB) START   The logic "1" received after acknowledge of a write bit (R/W = 0)
                defines the beginning of the control byte.
6, 5, 4 SEL2,   These three bits select the desired "ON" channel (Table 2).
        SEL1,
        SEL0
3       RNG     Selects the full-scale input voltage range (Table 3).
2       BIP     Selects unipolar or bipolar conversion mode (Table 3).
1, 0    PD1,    These two bits select the power-down modes (Table 4).
        PD0

Table 2. Channel Selection
SEL2  SEL1  SEL0  CHANNEL
0     0     0     CH0
0     0     1     CH1
0     1     0     CH2
0     1     1     CH3
1     0     0     CH4
1     0     1     CH5
1     1     0     CH6
1     1     1     CH7

Table 3. Range and Polarity Selection
INPUT RANGE (V) RNG BIP   NEGATIVE FULL   ZERO        FULL SCALE (V)
                          SCALE (V)       SCALE (V)
MAX127
0 to 5          0   0     â€“               0           VREF x 1.2207
0 to 10         1   0     â€“               0           VREF x 2.4414
±5              0   1     -VREF x 1.2207  0           VREF x 1.2207
±10             1   1     -VREF x 2.4414  0           VREF x 2.4414

MAX128
0 to VREF/2     0   0     â€“               0           VREF/2
0 to VREF       1   0     â€“               0           VREF
±VREF/2         0   1     -VREF/2         0           VREF/2
±VREF           1   1     -VREF           0           VREF

Table 4. Power-Down and Clock Selection
PD1 PD0 MODE
0   X   Normal Operation (always on)
1   0   Standby Power-Down Mode (STBYPD)
1   1   Full Power-Down Mode (FULLPD)

*/



#define MAX127_I2C_ADDR 0x50


/* int readMAX127(char port, byte _address, byte _channel);*/


// This function allows conversion of an unsigned byte to a signed int.
// This is a work-around for RobotC bug entry 222
// http://www.education.rec.ri.cmu.edu/tools/mantis/view.php?id=222


// Returns the current analogue value as measured on the specified channel.
int readMAX127(char port, byte address, byte channel)
{
   byte I2Crequest[2];

   // Control Byte: start bit (7) + channel number bit-shifted into place
   byte control= (1 << 7) + (channel << 4);

   I2Crequest[0]=address;     // I2C Address
   I2Crequest[1]=control;     // Control Byte
   

   byte I2Creply[2] = {0, 0};   // I2C reply is 2 bytes
   int  chVal = 0;              // ADC channel value after bit shifting of reply



   clearI2CBus(port);
   I2CWaitUntilReady(port);

   I2CWrite(port, 2, I2Crequest); // Send our request for the value of the channel
   I2CWaitUntilReady(port);

   I2CRead(port, 2, I2Creply);   // Read the 2 byte long reply into the array

   chVal = (I2Creply[0] << 4) + (I2Creply[1] >> 4);

   return chVal;
}




/*
    RobotC Microchip MCP23008 driver
    Author: Xander Soldaat
    Date: 09/09/2008
    Version: 0.2
    Contact: mightor_at_gmail.com
    Usage:
    * MCP23008WriteReg(Sensor, I2C Addr (0x00 - 0x7F), Register (0x00-0x0A), Data)
                                              Writes specified data to regiser
    * MCP23008ReadReg(Sensor, I2C Addr (0x00 - 0x7F), Register (0x00-0x0A))
                                              Reads specified regiser and returns data (byte)

    Note:

    THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 1.40 AND HIGHER.
*/


// Registers
#define MCP_REG_IODIR   0x00    // I/O DIRECTION REGISTER
#define MCP_REG_IPOL    0x01    // INPUT POLARITY REGISTER
#define MCP_REG_GPINTEN 0x02    // INTERRUPT-ON-CHANGE CONTROL REGISTER
#define MCP_REG_DEFVAL  0x03    // DEFAULT COMPARE REGISTER FOR INTERRUPT-ONCHANGE
#define MCP_REG_INTCON  0x04    // INTERRUPT CONTROL REGISTER
#define MCP_REG_IOCON   0x05    // CONFIGURATION REGISTER
#define MCP_REG_GPPU    0x06    // PULL-UP RESISTOR CONFIGURATION REGISTER
#define MCP_REG_INTF    0x07    // INTERRUPT FLAG (INTF)REGISTER
#define MCP_REG_INTCAP  0x08    // INTERRUPT CAPTURE REGISTER
#define MCP_REG_GPIO    0x09    // PORT REGISTER
#define MCP_REG_OLAT    0x0A    // OUTPUT LATCH REGISTER

// Special bits in the IOCON register
#define MCP_BIT_INTPOL  1       // This bit sets the polarity of the INT output pin
#define MCP_BIT_ODR     2       // This bit configures the INT pin as an open-drain output
#define MCP_BIT_DISSLW  4       // Slew Rate control bit for SDA output
#define MCP_BIT_SREAD   5       // Sequential Operation mode bit

#define MCP_I2C_ADDR    0x40    // Default base address (A0-A2 tied to gnd)



/*
  =============================================================================
  Write data to the device at the specified register

 */
void MCP23008WriteReg(char port, byte addr, byte reg, byte data) {
   byte _I2CRequest[3];

     _I2CRequest[0] =  addr;            // I2C Address
     _I2CRequest[1] =  reg;             // Register address
     _I2CRequest[2] =  data;            // Data to be sent


  clearI2CBus(port);
  I2CWaitUntilReady(port);

  I2CWrite(port, 0, _I2CRequest);
  I2CWaitUntilReady(port);
}



/*
  =============================================================================
  Write data to the device at the specified register

*/
byte MCP23008ReadReg(char port, byte _addr, byte _reg) {
   byte _I2CRequest[2];

   _I2CRequest[0] =  _addr;            // I2C Address
   _I2CRequest[1] =  _reg;             // Register address

  byte _I2CReply[1];  // Reply of request


  clearI2CBus(port);
  I2CWaitUntilReady(port);


  I2CWrite(port, 1, _I2CRequest);
  I2CWaitUntilReady(port);

  I2CRead(port, 1, _I2CReply);
  I2CWaitUntilReady(port);

  return _I2CReply[0];
}


/*void MCP23008SetupIOpup(char port, byte _addr, byte _mask, byte _pullup) {
   MCP23008WriteReg(port, _addr, MCP_REG_IODIR, _mask);
   MCP23008WriteReg(port, _addr, MCP_REG_GPPU, _pullup);
} */


void MCP23008SetupIO(char port, byte _addr, byte _mask) {
   MCP23008WriteReg(port, _addr, MCP_REG_IODIR, _mask);
}



byte MCP23008ReadIO_M(char port, byte _addr, byte _mask) {
   return MCP23008ReadReg(port, _addr, MCP_REG_GPIO) & _mask;
}



byte MCP23008ReadIO(char port, byte _addr) {
   return MCP23008ReadReg(port, _addr, MCP_REG_GPIO);
}



void MCP23008WriteIO(char port, byte _addr, byte _mask) {
   MCP23008WriteReg(port, _addr, MCP_REG_OLAT, _mask);
}



byte enabledSensors_ = 0;

// Allows for sensors to be enabled and disabled according to the mask, 1 is on, 0 is off


void enableSensors(byte port, byte _mask) {
  enabledSensors_ = _mask;
  MCP23008SetupIO(port, MCP_I2C_ADDR, 0x0);
  MCP23008WriteIO(port, MCP_I2C_ADDR, _mask);
}


// Get the ADC value of the associated channel, return -1 of the sensor was not enabled.

int readSensor(byte port, byte _channel, byte _precision) {
   if ((enabledSensors_ >> _channel) & 1) {
     return readMAX127(port, MAX127_I2C_ADDR, _channel) >> (12 - _precision);
   }
   else {  return -1; }
}




task main() {
   int M_counter = 0;
   int M_sensorVal = 0;


   ClearScreen();
   TextOut(0,56, "MightyBoard v1.0");


   // setup the link to the board
   
   SetSensorLowspeed(MB_port);
   enableSensors(MB_port, 0xFF);

   ClearScreen();
   
   while (true) {

    for (M_counter = 0; M_counter < 8; M_counter++) {

       M_sensorVal = readSensor(MB_port, M_counter, 12);

       if (M_sensorVal < 0) {
          PlayTone(880, 500);  Wait(500);
          PlayTone(1760, 500); Wait(500);
          PlayTone(880, 500);  Wait(500);
          PlayTone(1760, 500); Wait(500);
          Wait(20000);
       }

      printf2v(0, 56-(8*M_counter), "%2d ","%4d", M_counter,  M_sensorVal);
      Wait(5);
    }
   }


}
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
Sebi
Administrator
Administrator
Beiträge: 1946
Registriert: 11. Jan 2008 14:28
Wohnort: Aub
Kontaktdaten:

Beitragvon Sebi » 1. Mär 2010 14:08

4x Lichtsensor Multiplexer
Schaltplan:
Bild
Der Multiplexer selber
Bild
Selbstbau Lichtsensoren.
Treiber:

Code: Alles auswählen

byte Adress[];
byte Adressread;
byte I2CMsg[];
byte Command;
byte Light[];
int hoch(int zahl,int potenz)
{
 int result=zahl;
 if(potenz!=0)
 {
  for(int i=1;i<potenz;i++)
  {
  result=result*zahl;
  }
 }
 else
 {
  result=1;
 }
 return result;
}
void SetSensorLSMux(char SensorPort,char SensorNumber,char SensorI2CAdress)
{
 ArrayInit(Adress,0,7);
 ArrayInit(Light,0,7);
 SetSensorLowspeed(SensorPort);
 Adress[SensorNumber]=SensorI2CAdress;
 Adressread=Adress[SensorNumber];
 ArrayBuild(I2CMsg,Adressread,0x00);
 I2CWrite(SensorPort,1,I2CMsg);
}
void LSMuxSetLightOn(char SensorPort,char LightNumber, char SensorNumber)
{
 Adressread=Adress[SensorNumber];
 if((Light[SensorNumber]-(hoch(2,(LightNumber+4))))<0)
 {
  Light[SensorNumber] += hoch(2,(LightNumber+4));
  Command = Light[SensorNumber];
  ArrayBuild(I2CMsg,Adressread,Command);
  I2CWrite(SensorPort,1,I2CMsg);
  Wait(8);
 }
}
void LSMuxSetLightOff(char SensorPort,char LightNumber, char SensorNumber)
{
 Adressread=Adress[SensorNumber];
 if((Light[SensorNumber]-(hoch(2,(LightNumber+4))))>0)
 {
  Light[SensorNumber]-=hoch(2,(LightNumber+4));
  Command = Light[SensorNumber];
  ArrayBuild(I2CMsg,Adressread,Command);
  I2CWrite(SensorPort,1,I2CMsg);
  Wait(8);
 }
}
void LSMuxSetLights(char SensorPort,char Lights,char SensorNumber)
{
 Adressread=Adress[SensorNumber];
 Light[SensorNumber]=Lights*16;
 Command = Light[SensorNumber];
 ArrayBuild(I2CMsg,Adressread,Command);
 I2CWrite(SensorPort,1,I2CMsg);
 Wait(8);
}
int LSMuxReadSensor(char SensorPort,char Number,char SensorNumber)
{
 Adressread=Adress[SensorNumber];
 int result;
 Command = Light[SensorNumber]+(hoch(2,Number));
 ArrayBuild(I2CMsg,Adressread,Command);
 I2CWrite(SensorPort,1,I2CMsg);
 Wait(8);
 SetSensorLight(SensorPort);
 result=SensorRaw(SensorPort);
 SetSensorLowspeed(SensorPort);
 Wait(8);
 Command = Light[SensorNumber];
 ArrayBuild(I2CMsg,Adressread,Command);
 I2CWrite(SensorPort,1,I2CMsg);
 Wait(8);
 return result;
}

Der Mux ist Kaskadierbar.(Bis zu 8 Stück an einem Port, wenn man PCF8574P und PCF8574A benutzt, kann man 16 an einen Port anschließen.)
Der PCF8574 kann die LEDs der LSs an und aus schalten. Beim lesen schaltet er per Transistor Pin1/ADA für den jeweiligen Sensor durch.
Man kann naürlich auch NXT Lichtsensoren benutzen, dann muss man aber die Pinbelegung ändern. Die Lichtsensoren können auch ohne Mux direkt am NXT betrieben werden, dann muss man aber auch die Pinbelegung ändern.
Mit dem Jumper (J3) kann man eine externe Spannungsquelle jumpern.
Bei einem Muxer braucht man das aber nicht.

Programm erklärung:
SetSensorLSMux(SensorPort,char SensorNummer,I2CAdresse);
Braucht man um den Sensor zu konfigurien./setzen.
SensorPort erklärt sich von alleine.
Mit SensorNummer kann man, wenn man mehrere Muxs am NXT betreiben will, die einzelnen Muxs durchnummeriren.
Bei I2CAdresse muss man die I²C Adresse vom jeweiligen PCF8574 angeben.

LSMuxSetLightOn(char SensorPort,char LightNumber, char SensorNumber) Braucht man, um eine einzelne LED der Sensoren an zu machen.
LightNumber Nummer der LED die man anmachen will (0-3)

LSMuxSetLightOff(char SensorPort,char LightNumber, char SensorNumber) Braucht man, um eine einzelne LED der Sensoren aus zu machen.
LightNumber Nummer der LED die aus anmachen will (0-3)

void LSMuxSetLights(char SensorPort,char Lights,char SensorNumber) Braucht man um alle (4) LEDs eines Muxs auf einmal an oder aus zu machen.
Lights Hex-Code 0x0-0xF je nach Kombination.

LSMuxReadSensor(char SensorPort,char Number,char SensorNumber)
Braucht man zum Sensorauslesen. Man kann nur einen LS gleichzeitig auslesen.
Number ist die Nummer des Sensors (0-3)
<img src="http://my-lego-page.cwsurf.de/mux1.JPG" widht="792" height="594">
Hier ein Bild vom Steckboard Aufbau
<img src="http://my-lego-page.cwsurf.de/mux2.JPG" widht="792" height="594">
Und hier nochmal die Selbstbau Lichtsensoren.
Die 4erFlachbandkabel sind für die 3 Sensoren.

Benutzeravatar
Sebi
Administrator
Administrator
Beiträge: 1946
Registriert: 11. Jan 2008 14:28
Wohnort: Aub
Kontaktdaten:

Beitragvon Sebi » 20. Mär 2010 12:47

Auch sehr Interesant:
http://www.daselektronikerforum.de/view ... ead#unread
PCA9555
Der hat 16 I/O Ports. Gibts aber nur bei DES(www.derelektronikershop.de)
(Also so wie der PCF8574 aber halt mit 16 I/Os. und nicht mit 8)

Benutzeravatar
Sebi
Administrator
Administrator
Beiträge: 1946
Registriert: 11. Jan 2008 14:28
Wohnort: Aub
Kontaktdaten:

df

Beitragvon Sebi » 1. Apr 2010 18:27

Kommunikation ohne Treiber
Senden
Oben wird mit dem PCF8574 per Treiber kommuniziert. Ohne extra IC Treiber ist es aber auch nicht so schwer.(Wie beim LSMux)
Dazu braucht man folgenden Code:

Code: Alles auswählen

byte I2CMsg[];
void I2CSend(char port, byte Command, byte Adress)
{
 ArrayBuild(I2CMsg,Adress,Command);
 I2CWrite(port,1,I2CMsg);
}

I2CMsg[] ist ein Array, in dem die eigentliche Nachricht gespeichert wird.
Bei port gibt man den Sensor Port an.
Bei command gibt man den Befehl, den man senden will, (so wie "WritePorts" oben). z.B. 0x0F.
Bei Adress gibt man die Adresse an, die Standard Adresse(A0-A2 auf Low) des PCF8574P ist 0x40.

Man kann das ganze auch ohne Makro ins Programm schreiben, aber so spart man sich viel Schreibarbeit, und das Programm wird kompakter.
Zuletzt geändert von Sebi am 3. Jan 2011 11:37, insgesamt 1-mal geändert.

flonxt
Schreibt viel
Schreibt viel
Beiträge: 141
Registriert: 3. Dez 2009 16:52

Beitragvon flonxt » 3. Jun 2010 19:36

@Sebi ich würde gerne 8 lichtsensoren an einem sensorport anschliessen
auf deiner homepage hab ich gesehen das sogar 16 lichtsensoren gehen
1.gibt es dafür auch einen schaltplan?
2.muss ich alle GND zusammen schliessen?
3.was muss ich mit vdd machen?
4.kann ich den jumper weglassen(was macht der überhaupt)?
5.wie ist die kommunikation ohne treiber und ohne array in verschiedene variablen(z.b.: int ls1, int ls2,...)?
6.kann ich als transistor bc548c nehmen?

ich weiss das sind viele fragen :oops:

Benutzeravatar
Sebi
Administrator
Administrator
Beiträge: 1946
Registriert: 11. Jan 2008 14:28
Wohnort: Aub
Kontaktdaten:

Beitragvon Sebi » 3. Jun 2010 20:07

Es würde (prinzipiel) 16 Muxer an einen Port gehen!
Also 8x mit PCF8574P und 8x mit PCF8574A. Die haben verschidene Standard-I²C Adressen.
Wenn du 8 nehmen willst, würde ich dir empfehlen einen PCA955N zu nehmen. Die gibts aber nur ber DES als DIP.(Also Kein SMD).
Dazu zeiche mal einen Schaltplan, den Treiber müsste ich dann auch noch ein wenig ändern...
2. GND muss immer zusammen geschlossen werden.
3. Das müsste dann an eine 5V Batterie.
4. Vdd ist die Spannung der Sensoren die wird entweder (mit dem Jumper) an den NXT oder an die Batterie angeschlossen.(Falls man mehrere an einem Port hat, dass die Stromversorgung auch langt.)
5. Wie meinst du dass genau?
6. Ja, sind doch angegeben, ich habe blos BC549C auf dem Steckboard, weil DES bei meiner Bestellung keine 100 BC548C mehr hatte...

Benutzeravatar
Sebi
Administrator
Administrator
Beiträge: 1946
Registriert: 11. Jan 2008 14:28
Wohnort: Aub
Kontaktdaten:

Beitragvon Sebi » 3. Jun 2010 20:44

Hier mal der geänderte Schaltplan:
Bild
Und hier mit 8 Lichtsensoren:
Bild
Der ist aber nicht geprüft, und ich müsste auch erst den Treiber dafür schreiben, weil man den PCD9555 anders ansteuern muss...

fossy
Hilft fleißig mit!!!
Hilft fleißig mit!!!
Beiträge: 61
Registriert: 14. Mai 2007 15:58

Warum 82k pull-up

Beitragvon fossy » 19. Okt 2010 07:54

Warum werden eigentlich 82kOhm als pull-up eingesetzt. Bei mir habe ich den Bus auch so aufgebaut, weiß aber, daß I²C auch locker mit 10kOhm funktioniert.
Wo habt ihr diese Vorgabe her?
LEGO HDK?
Danke!
fossy


Zurück zu „Projekte, Showcase, Bauanleitungen“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 9 Gäste

Lego Mindstorms EV3, NXT und RCX Forum : Haftungsauschluss