Hardware:
- NXT
- Arduino Nano V3
- MAX 485 CPA
- Protoboard (ou similar)
- Fios finos (tipo usado para Wrap)
Ambiente de programação:
– NXT firmware 1.28
– NXC nbc-1.2.1.r1
– Arduino 0018
– Mac OS X 10.6.3
Obsevações:
- Foi usado um Arduino Nano V3, mas outros modelos também podem usados;
- Inspirado pelo post Early stage RS 485 with MAX485 no fórum sobre arduino e pelo post RS485 to RS232 Adapter no fórum nxtasy.org;
- As funções seriais foram baseadas na biblioteca antiga de software serial do Arduino;
- Testados para velocidades entre 9600 and 57600; velocidades maiores, não trabalha
baudrate.h:
#define RS485_BAUD 57600
NCX Program: (Screenshot)
#include "baudrate.h"
#define TOWAIT 2000
#define MSG "Hello Arduino "
// -------------------------------------------------------------
void printMsg(byte inbuffer[], int cnt) {
TextOut(0, LCD_LINE3, " Baud");
NumOut(0, LCD_LINE3, RS485_BAUD);
TextOut(0, LCD_LINE5, "l= cnt= ");
NumOut(12, LCD_LINE5, ArrayLen(inbuffer));
NumOut(60, LCD_LINE5, cnt);
// "Hi NXT,got "
TextOut(0, LCD_LINE6, "rcv: ");
TextOut(24, LCD_LINE6, ByteArrayToStr(inbuffer));
}
// -------------------------------------------------------------
task main() {
int i = 0;
int cnt = 0;
byte outbuffer[];
byte inbuffer[];
char result;
SetSensorType(IN_4, SENSOR_TYPE_HIGHSPEED);
Wait(100);
// we use odd parity on the Arduino side
// see: http://forums.nxtasy.org/index.php?showtopic=3871
RS485Uart(HS_BAUD_##RS485_BAUD, HS_MODE_8_DATA|HS_MODE_O_PARITY|HS_MODE_10_STOP);
Wait(100);
StrToByteArray(MSG, outbuffer);
TextOut(0, LCD_LINE1, "RS485 <> Arduino");
while (true) {
outbuffer[14] = '0' + i;
i++; if (i==10) i = 0;
result = RS485Write(outbuffer);
while (!RS485DataAvailable()) {}
result = RS485Read(inbuffer);
printMsg(inbuffer, cnt);
cnt++; if (cnt==1000) cnt = 0;
Wait(TOWAIT);
}
}
Arduino sketch: (Screenshot)
#include "baudrate.h"
// Pins and wires
// Arduino Wire MAX485
const byte RS485_OUT_PIN = 10; // yellow --> DI
const byte RS485_IN_PIN = 11; // green --> RO
const byte RS485_CTL_PIN = 12; // grey --> RE+DE
// VCC --> VCC
// ------------------------------------------
// NXT Sensor Port 4 Wire MAX485
// DIGIAI1 blue --> B
// DIGIAI0 yellow --> A
// GND black --> GND
const byte RECV_RS485_BIT = B00001000;
const byte SEND_RS485_BIT = B00000100;
#define readRS485inPin (PINB & RECV_RS485_BIT)
const unsigned int BUFLEN = 128;
const unsigned int outnbuf = 12;
byte outBuf[BUFLEN];
byte inBuf [BUFLEN];
unsigned int innbuf;
const char msg[] = "Hi NXT,got ";
const byte SER_TIMEOUT = 7;
unsigned int RS485_LEN;
unsigned int bitDelay;
unsigned int halfBitDelay;
const byte CYCLES = 45;
// ------------------------------------------------------------------
void serSetup(unsigned long baud) {
pinMode(RS485_OUT_PIN, OUTPUT);
digitalWrite(RS485_OUT_PIN, LOW);
pinMode(RS485_IN_PIN, INPUT);
digitalWrite(RS485_IN_PIN, LOW);
pinMode(RS485_CTL_PIN, OUTPUT);
digitalWrite(RS485_CTL_PIN, LOW);
RS485_LEN = 1000000 / baud;
bitDelay = RS485_LEN - clockCyclesToMicroseconds(CYCLES);
halfBitDelay = RS485_LEN/2 - clockCyclesToMicroseconds(CYCLES);
Serial.print("\nRS-485 configured, ");
Serial.print(baud, DEC);
Serial.print(" Baud, Bit length ");
Serial.print(RS485_LEN, DEC);
Serial.println(" uSec");
}
// Startbit of 1st byte of incoming message encountered
// ------------------------------------------------------------------
byte serAvail() {
return readRS485inPin;
}
// Read a byte
// ------------------------------------------------------------------
unsigned int serRead() {
byte i;
int val = 0;
byte parity = 0, stopbit = 0;
long start = millis();
while (true) {
if (millis()-start>SER_TIMEOUT) return -1;
if (readRS485inPin) break; // startbit hit
}
delayMicroseconds(halfBitDelay); // jump to middle of startbit
for (i=0; i<8; i++) {
delayMicroseconds(bitDelay);
val |= !readRS485inPin << i; // data bits
}
delayMicroseconds(bitDelay);
parity = !readRS485inPin; //
delayMicroseconds(bitDelay);
stopbit = !readRS485inPin; //
return val;
}
// Write one bit
// -----------------------------------------------------------------
void serBit(byte mark) {
if (mark) PORTB &= ~ SEND_RS485_BIT;
else PORTB |= SEND_RS485_BIT;
// delayMicroseconds(RS485_LEN);
delayMicroseconds(bitDelay);
}
// Write a byte
// ------------------------------------------------------------------
void serWrite(byte data) {
byte mask = 1;
byte bitcount = 0;
serBit(LOW); // startbit
for (byte i=0; i<8; i++) { // data from LSB to MSB
if (data & mask) {
serBit(HIGH);
bitcount++;
} else {
serBit(LOW);
}
mask <<= 1;
}
serBit((bitcount%2)==0); // odd parity bit
serBit(HIGH); // stop bit
}
// ------------------------------------------------------------------
void printMsg(const char *s, byte buf[], int nbuf) {
Serial.print(s);
Serial.print(": \"");
for (int i=0; i<nbuf; i++)
Serial.print(buf[i], BYTE);
Serial.println("\"");
}
// ------------------------------------------------------------------
void serSendMsg(byte buf[], int nbuf) {
int i;
digitalWrite(RS485_CTL_PIN, HIGH);
for (i=0; i<nbuf; i++)
serWrite(buf[i]);
digitalWrite(RS485_CTL_PIN, LOW);
}
// ------------------------------------------------------------------
int serRecvMsg(byte buf[]) {
int c;
int nbuf = 0;
while ((c = serRead())!=-1)
buf[nbuf++] = c;
return nbuf;
}
// ------------------------------------------------------------------
void measureComms(byte stage) {
static unsigned long old = 0;
unsigned long now;
if (!stage) {
old = millis();
} else {
now = millis();
Serial.print("comms took ");
Serial.print(now-old, DEC);
Serial.println(" mSec");
}
}
// ------------------------------------------------------------------
void setup() {
Serial.begin(9600);
for (int i=0; i<outnbuf; i++)
outBuf[i] = msg[i];
outBuf[12] = 0;
serSetup(RS485_BAUD);
}
// ------------------------------------------------------------------
void loop() {
// measureComms(0);
if (serAvail()) {
innbuf = serRecvMsg(inBuf);
outBuf[11] = inBuf[innbuf-1];
serSendMsg(outBuf, outnbuf);
// measureComms(1);
printMsg("Recv", inBuf, innbuf);
printMsg("Sent", outBuf, outnbuf);
}
}
Fontes:
Este comentário foi removido pelo autor.
ResponderExcluirBoa noite!
ResponderExcluirComo faço pra acionar um motor de lego direto? Quero liga-lo direto a uma bateria, tenho um cabo cortado. Como faço? Quais dos 6 fios eu uso?