Программирование Arduino+NXTI2CDEVICE

Borolis
Offline
Зарегистрирован: 03.02.2013

Вообщем я только начал осваиваться с arduino ,мне необходимо реализовать управление 2 сервами через serial ,serial часть у меня работает и все вроде бы хорошо но нужно подключить сервы от lego примерно так

http://robotclub.ab.ca/articles/33  ,вроде закидываю библиотеку вот сюда >>   Desktop\arduino-1.0.2\libraries\тут папка NXTI2CDevice и в ней файлы cpp и .h , так как у меня версия 1,02 я во всех файлах папки во всех .h и .cpp заменил 

#include "WProgram.h"

 на: 

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif 

вот как то так но мне при компиляции примера пишет вот что 

 

E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\BaseNXTI2CDevice.cpp: In member function 'uint8_t* NXTI2CDevice::readRegisters(uint8_t, uint8_t, uint8_t*, uint8_t, bool)':
E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\BaseNXTI2CDevice.cpp:84: error: 'class TwoWire' has no member named 'send'
E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\BaseNXTI2CDevice.cpp:93: error: 'class TwoWire' has no member named 'receive'
E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\BaseNXTI2CDevice.cpp: In member function 'bool NXTI2CDevice::writeRegisters(uint8_t, uint8_t, uint8_t*)':
E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\BaseNXTI2CDevice.cpp:152: error: 'class TwoWire' has no member named 'send'
E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\BaseNXTI2CDevice.cpp:158: error: 'class TwoWire' has no member named 'send'
E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\/../Wire/utility/twi.h: In member function 'bool NXTI2CDevice::checkAddress()':
E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\/../Wire/utility/twi.h:44: error: too few arguments to function 'uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t)'
E:\Users\Борис\Desktop\arduino-1.0.2\libraries\NXTI2CDevice\BaseNXTI2CDevice.cpp:235: error: at this point in file
 

мне как бы главное чтобы компилировались и работали эти примера а дальше я уже сам допилю их до нужного мне уровня

 

заранее спасибо!

PLEAAASE! HEEEELP! ME!

 

maksim
Offline
Зарегистрирован: 12.02.2012

Замените содержимое файлов:

  NXTI2CDevice.h

// NXTI2CDevice.h
//
// This is a class for controlling some LEGO Mindstorms NXT devices that
// communicate using the I2C protocol. 
//
// Use at your own risk!
//
// Initial version: 2010-05-31 by Clinton Blackmore

/*
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef BASENXTI2CDEVICE_H
#define BASENXTI2CDEVICE_H

#include <Arduino.h>
//#include <Wiring.c>
#include <inttypes.h>

inline uint16_t readIntFromBuffer(uint8_t* buf)
{
	return buf[0] | (buf[1] << 8);
}

inline uint32_t readLongFromBuffer(uint8_t* buf)
{
	return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
}

inline void writeByteToBuffer(uint8_t* buf, uint8_t data)
{
	buf[0] = data;
}

inline void writeByteToBuffer(uint8_t* buf, int8_t data)
{
	writeByteToBuffer(buf, (uint8_t)data);
}

inline void writeIntToBuffer(uint8_t* buf, uint16_t data)
{
	buf[0] = data & 0xFF;
	buf[1] = (data >> 8) & 0xFF;
}

inline void writeIntToBuffer(uint8_t* buf, int16_t data)
{
	writeIntToBuffer(buf, (uint16_t)data);
}

inline void writeLongToBuffer(uint8_t* buf, uint32_t data)
{
	buf[0] = data & 0xFF;
	buf[1] = (data >>  8) & 0xFF;
	buf[2] = (data >> 16) & 0xFF;
	buf[3] = (data >> 24) & 0xFF;
}

inline void writeLongToBuffer(uint8_t* buf, int32_t data)
{
	writeLongToBuffer(buf, (uint32_t)data);
}

class NXTI2CDevice
{
	// Note that this class is a base class, but not an abstract base class
	// Feel free to instantiate NXTI2CDevices.
	
public:

	NXTI2CDevice(uint8_t i2c_address);

	// Routines to read registers from the I2C device
	// Only the first two parameters are required.
	uint8_t* 	readRegisters	(uint8_t start_register, uint8_t bytes_to_read,
								uint8_t* buffer = 0, uint8_t buffer_length = 0, bool clear_buffer = false);

	uint8_t  	readByte	(uint8_t location);
	uint16_t  	readInteger	(uint8_t location);
	uint32_t  	readLong	(uint8_t location);
	char* 		readString	(uint8_t  location, uint8_t  bytes_to_read,
							 uint8_t* buffer = 0, uint8_t  buffer_length = 0);


	// Routines to write data to registers of the I2C device

	bool 		writeRegisters	(uint8_t start_register, uint8_t bytes_to_write,
								uint8_t* buffer = 0);

	bool 		writeByte	(uint8_t location, uint8_t data);
	bool 		writeInteger(uint8_t location, uint16_t data);
	bool 		writeLong	(uint8_t location, uint32_t data);

	bool checkAddress();
	bool setAddress(uint8_t i2c_address);
	uint8_t getAddress();

	uint8_t		getWriteErrorCode();

	// Read some strings from the device.
	// (I believe this is consistent for all NXT I2C devices).
	char*		getFirmwareVersion();
	char*		getVendorID();
	char*		getDeviceID();


protected:

	static uint8_t* _buffer;	// Buffer used for data that is returned from I2C commands

	void		setWriteErrorCode(uint8_t code);

private:

	uint8_t _device_address;	// I2C address of the NXT device
	uint8_t _write_error_code;	// Error code from last write
};

#endif // BASENXTI2CDEVICE_H

  
 NXTI2CDevice.cpp

// NXTI2CDevice.cpp
//
// This is a base class for NXT sensors that use the I2C protocol.
//
// 2010-05-31 - Initial version, by Clinton Blackmore
//
/*
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/


#include "BaseNXTI2CDevice.h"
#include <Wire.h>

extern "C" {
#include "../Wire/utility/twi.h"
}

// Max I2C message length is 16 bytes.  
const int BUFFER_LEN = 16;	


// Initialize static variables
uint8_t* NXTI2CDevice::_buffer = 0;


NXTI2CDevice::NXTI2CDevice(uint8_t i2c_address)
{
	// As I understand it, an I2C bus can address 127 different devices (a 7-bit quantity).
	// When used, the 7-bit quantity is shifted right one bit, and the last bit is clear
	// for a read operation and set for a write operation.  Arduino's Wire library expects
	// a 7-bit address, but most tech specs list the 8-bit address.  Hence, we drop
	// the least significant bit (and Wire.h shifts the address and sets the read/write
	// bit as appropriate.)
	_device_address = i2c_address >> 1;
	Wire.begin();

	_buffer = (uint8_t*) calloc(BUFFER_LEN, sizeof(uint8_t));
}

// READING FUNCTIONS

// Reads registers of an I2C device.
// See the documentation for your device to know what a given register
// or register range indicates.
uint8_t* NXTI2CDevice::readRegisters(
	uint8_t  start_register, 	// start of the register range
	uint8_t  bytes_to_read, 	// number of bytes to read
	uint8_t* buffer,			// (optional) user-supplied buffer
	uint8_t  buffer_length,		// (optional) length of user-supplied buffer
	bool     clear_buffer)		// should we zero out the buffer first? (optional)
{
	if (!buffer)
	{
		buffer = _buffer;
	}

	if (!buffer_length)
	{
		buffer_length = BUFFER_LEN;
	}

	bytes_to_read = min(bytes_to_read, buffer_length);	// avoid buffer overflow

	if (clear_buffer)
	{
		memset(buffer, 0, buffer_length);
	}

	// We write to the I2C device to tell it where we want to read from
	Wire.beginTransmission(_device_address);
  	Wire.write(start_register);
  	//Wire.send(bytes_to_read);
  	Wire.endTransmission();

  	// Now we can read the data from the device
	Wire.requestFrom(_device_address, bytes_to_read);

    for (uint8_t index = 0; Wire.available(); ++index)
    {
    	buffer[index] = Wire.read();
    }

    Wire.endTransmission();

	return buffer;
}

// Reads a byte from the given register on the I2C device.
uint8_t NXTI2CDevice::readByte(uint8_t location)
{
	readRegisters(location, 1);
	return _buffer[0];
}

// Reads two bytes from the given register pair on the I2C device.
uint16_t NXTI2CDevice::readInteger(uint8_t location)
{
	readRegisters(location, 2);

	// I believe the data has the least significant byte first
	return readIntFromBuffer(_buffer);
}

// Reads four bytes from the given registers, starting at the specified location, on the I2C device.
uint32_t NXTI2CDevice::readLong(uint8_t location)
{
	readRegisters(location, 4);
	return readLongFromBuffer(_buffer);
}

// Reads a string.  Be certain that your buffer is large enough
// to hold the string and a trailing 'nul'!
char* NXTI2CDevice::readString(
		uint8_t  location, 			// starting location of the string
		uint8_t  bytes_to_read, 	// number of bytes to read
		uint8_t* buffer,			// optional user-supplied buffer
		uint8_t  buffer_length)		// length of user-supplied buffer)
{
	return (char *)readRegisters(location, bytes_to_read, buffer, buffer_length, true);
}


// WRITING FUNCTIONS

// Returns true if the write was successful.
// If not true, you may check the result by calling getWriteErrorCode.
bool NXTI2CDevice::writeRegisters(
	uint8_t  start_register, 	// start of the register range
	uint8_t  bytes_to_write, 	// number of bytes to write
	uint8_t* buffer)		// optional user-supplied buffer
{
	if (!buffer)
	{
		buffer = _buffer;
	}

	// We write to the I2C device to tell it where we want to read from and how many bytes
	Wire.beginTransmission(_device_address);
  	Wire.write(start_register);
  	//Wire.send(bytes_to_write);	// This is a guess
  	
  	// Send the data
  	for (uint8_t index = 0; index < bytes_to_write; ++index)
  	{
  		Wire.write(buffer[index]);
  	}

  	_write_error_code = Wire.endTransmission();

  	return _write_error_code == 0;	// 0 indicates success
}

// Writes a byte to a given register of the I2C device
bool NXTI2CDevice::writeByte(uint8_t location, uint8_t data)
{
	return writeRegisters(location, 1, &data);
}

// Writes two bytes to a given register of the I2C device
bool NXTI2CDevice::writeInteger(uint8_t location, uint16_t data)
{
	writeIntToBuffer(_buffer, data);
	return writeRegisters(location, 2, _buffer);
}

// Writes four bytes to a given register of the I2C device
bool NXTI2CDevice::writeLong(uint8_t location, uint32_t data)
{
	writeLongToBuffer(_buffer, data);
	return writeRegisters(location, 4, _buffer);
}

// This is the status value returned from the last write command.
// A return value of zero indicates success.
// Non-zero results indicate failures.  From libraries/Wire/utility/twi.c, they are:
//          1 .. length to long for buffer
//          2 .. address send, NACK received
//          3 .. data send, NACK received
//          4 .. other twi error (lost bus arbitration, bus error, ..)
uint8_t NXTI2CDevice::getWriteErrorCode()
{
	return _write_error_code;
}

// READ SOME INFORMATION OFF OF THE DEVICE
// returns a string with the current firmware version of the device
char* NXTI2CDevice::getFirmwareVersion()
{
	return readString(0, 8);
}

// returns a string indicating the vendor of the device
char* NXTI2CDevice::getVendorID()
{
	return readString(0x08, 8);
}

// returns a string indicating the device's ID
char* NXTI2CDevice::getDeviceID()
{
	return readString(0x10, 8);
}

// It is very unusual to do this
void NXTI2CDevice::setWriteErrorCode(uint8_t code)
{
	_write_error_code = code;
}


/*
 * checkAddress()
 * this function checks to see if there is 
 * any device at a given address 
 * - deepak
 */

bool NXTI2CDevice::checkAddress()
{
	uint8_t *txBuffer;
	int8_t x = 1;
	x = twi_writeTo(_device_address, txBuffer, 0, 1, 0) == 0;
	return (x != 0);
}


/*
 * setAddress(address)
 * this function set's the i2c address
 * for this instance to given address 
 * Note that, generally i2c address of a physical device does not change.
 * Use this function if there are multiple devices on your bus and you want to 
 * conserve processor memory from instantiating another class instance.
 * - deepak
 */

bool NXTI2CDevice::setAddress(uint8_t i2c_address)
{
	_device_address = i2c_address >> 1;
	return true;
}

uint8_t NXTI2CDevice::getAddress()
{
	return _device_address;
}

или скачайте уже отредактированную либу.

Borolis
Offline
Зарегистрирован: 03.02.2013

Спасибо большое сейчас проверю , отпишусь

 

P.S. Так и думал что вы ответите )

побегал по темам вы почти везде даете дельные советы

Borolis
Offline
Зарегистрирован: 03.02.2013

да спасибо все откомпилилось

и если не секрет... где вы берете свежие библиотеки?

 

 

Borolis
Offline
Зарегистрирован: 03.02.2013

Максим? дело в том , что программы все компилируются ,но двигатели не крутятся и скетч который считывает данные с них на com порт отсылает это:

Vendor:

Device:  

Version: 
 
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
M1 pos: 0   M2 pos: 0
 
и происходит все только когда я хотябы чучуть его вращаю если что могу кинуть видео
 
 
maksim
Offline
Зарегистрирован: 12.02.2012

Попробуйте в NXTI2CDevice.cpp изменить строку 235

    x = twi_writeTo(_device_address, txBuffer, 0, 1, 0) == 0;

на

    x = twi_writeTo(_device_address, txBuffer, 0, 1, 1) == 0;

 

Borolis
Offline
Зарегистрирован: 03.02.2013

сейчас ок!

хммм нету .cpp есть только .h

Borolis
Offline
Зарегистрирован: 03.02.2013

строчку нашел в cpp файле и заменил

но ничего ничего не изменилось

 

maksim
Offline
Зарегистрирован: 12.02.2012

Так а как у вас все подключено? Дуина какая?

Borolis
Offline
Зарегистрирован: 03.02.2013

Arduino UNO Atmega328P-P'J

подключено так : +5V Arduino -->> VBUS

GND Arduino -->> GRND

ANALOG IN A5 Arduino -->> SCL

ANALOG IN A4 Arduino -->> SDA

 

mailru агентом пользуетесь? добавьте если что я заявку кинул там по быстрее =) 

если что Borolis@mail.ru

maksim
Offline
Зарегистрирован: 12.02.2012

В примерах есть I2CScanner, попробуйте, найдет ли он ваши девайсы.

Borolis
Offline
Зарегистрирован: 03.02.2013

залил

 

Scanning 2 to 40 ...
Checking Address 2 .... 
далее ничего не происходит 
если начать вращать серву 
тогда ,причем когда поворачиваю на граду 1 примерно кидает следующую строчку
 
Checking Address 4 .... no device found.
повернул чучуть
Checking Address 6 .... no device found.
повернул чучуть
Checking Address 8 .... no device found.
повернул чучуть
Checking Address 10 .... no device found.
повернул чучуть
Checking Address 12 .... no device found.
повернул чучуть
Checking Address 14 .... no device found.
повернул чучуть
Checking Address 16 .... no device found.
повернул чучуть
Checking Address 18 .... no device found.
повернул чучуть
Checking Address 20 .... no device found.
повернул чучуть
Checking Address 22 .... no device found.
повернул чучуть
Checking Address 24 .... no device found.
повернул чучуть
Checking Address 26 .... no device found.
повернул чучуть
Checking Address 28 .... no device found.
повернул чучуть
Checking Address 30 .... no device found.
повернул чучуть
Checking Address 32 .... no device found.
повернул чучуть
Checking Address 34 .... no device found.
повернул чучуть
Checking Address 36 .... no device found.
повернул чучуть
Checking Address 38 .... no device found.
повернул чучуть
Checking Address 40 .... no device found.
 
I2C Scan Complete.
 

 

maksim
Offline
Зарегистрирован: 12.02.2012

В общем, попробуйте с другой стороны зайти. Скачайте Arduino0023 и эту библиотеку в оригинале.

Borolis
Offline
Зарегистрирован: 03.02.2013

происходит все в точности тоже самое

я только вот немогу понять одно, в том видео у мужичка подключено 2 таких сервы и на одном моменте написано как подключено http://youtu.be/ixUF2UhLpk8?t=34s всетаки там же 2 сервы и какн он их тогда подключил? обе посадил на одни и те же контакты?

 

Borolis
Offline
Зарегистрирован: 03.02.2013

если есть возможность зайдите в агент? 

maksim
Offline
Зарегистрирован: 12.02.2012

Borolis пишет:

происходит все в точности тоже самое

я только вот немогу понять одно, в том видео у мужичка подключено 2 таких сервы и на одном моменте написано как подключено http://youtu.be/ixUF2UhLpk8?t=34s всетаки там же 2 сервы и какн он их тогда подключил? обе посадил на одни и те же контакты?

Конечно, это шина I2C при однобайтовой адресации позволяет на одни и теже два провода подключить до 127 устройств.

Borolis
Offline
Зарегистрирован: 03.02.2013

хорошо сейчас все подключу обратно

 

Borolis
Offline
Зарегистрирован: 03.02.2013

я вот незнаю что делать , завтра пойду поменяю сервы на другие,может с этими что не так?

 

maksim
Offline
Зарегистрирован: 12.02.2012

Вот еще какой момент был упущен - на линиях SDA и SCL должны стоять подтягивающие резисторы к +5V по 4,7кОм.

Borolis
Offline
Зарегистрирован: 03.02.2013

если к +5V то как я понимаю можно активировать Внутреннй подтягивающий резистор.

В микроконтроллерах ATmega168 и ATmega328 есть внутренние подтяжки. Они имеют номинал 20Ком и включаются программно. Нужно иметь в виду что внутренняя подтяжка "Прижимает" пин только к +5в ?

Или это возможно только для цифровых пинов?

 

Borolis
Offline
Зарегистрирован: 03.02.2013

Сейчас притянул SDA и SCL к +5в но все по прежнему

maksim
Offline
Зарегистрирован: 12.02.2012

Сопротивление подтяжки около 60кОм, что примерно в 12 раз больше нужного, попробуйте поставить резисторы на 4,7кОм и посмотреть через I2CScanner.

Borolis
Offline
Зарегистрирован: 03.02.2013

Подтянул резисторами 4,67 кОм и ничего не изменилось

maksim
Offline
Зарегистрирован: 12.02.2012

Еще раз перепроверьте правильность подключения и прозвоните линии, выложите фото.
И попробуйте вот этот сканер:

// --------------------------------------
// i2c_scanner
//
// This program (or code that looks like it)
// can be found in many places.
// For example on the Arduino.cc forum.
// The original author is not know.
//
// This sketch tests the standard 7-bit addresses
// from 0 to 127. Devices with higher bit address
// might not be seen properly.
//
// Adapted to be as simple as possible by Arduino.cc user Krodal
//
// June 2012
// Using Arduino 1.0.1
//

#include <Wire.h>


void setup()
{
  Wire.begin();

  Serial.begin(9600);
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 0; address <= 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println(" !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknow error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(8000);           // wait 8 seconds for next scan
}

 

Borolis
Offline
Зарегистрирован: 03.02.2013

 

 
I2C Scanner
Scanning...
тут все тормозится ..(( 
а если покрутить серву идет дальше
I2C device found at address 0x00 !
Unknow error at address 0x01
Unknow error at address 0x02
Unknow error at address 0x03
Unknow error at address 0x04
Unknow error at address 0x05
 
Borolis
Offline
Зарегистрирован: 03.02.2013

Вопрос до сих пор не решен, с заведомо рабочими серво-двигателями тоже не работает,проблема либо в коде либо в подключении