John Hansen,
I tried just about everything I could think of. I know I didn't intentionally put the RS485 into DATA_MODE_NXT. The only way it wasn't DATA_MODE_RAW, is if one of the RS485 setup functions changed it. Anyhow, here is the RS485 initialization code:
Code: Select all
void nxtSetHSBaudRate(long baudrate){
switch (baudrate){
case 9600:
SetHSSpeed(HS_BAUD_9600);
break;
case 19200:
SetHSSpeed(HS_BAUD_19200);
break;
case 38400:
SetHSSpeed(HS_BAUD_38400);
break;
case 57600:
SetHSSpeed(HS_BAUD_57600);
break;
case 115200:
SetHSSpeed(HS_BAUD_115200);
break;
case 230400:
SetHSSpeed(HS_BAUD_230400);
break;
case 460800:
SetHSSpeed(HS_BAUD_460800);
break;
case 921600:
SetHSSpeed(HS_BAUD_921600);
break;
}
}
void nxtEnableHSPort(long baudrate = 0){
SetSensorType(S4, SENSOR_TYPE_HIGHSPEED);
SetHSFlags(HS_UPDATE);
SetHSState(HS_INITIALISE);
SetHSFlags(HS_UPDATE);
if (baudrate) nxtSetHSBaudRate(baudrate);
SetHSFlags(HS_UPDATE);
}
void nxtDisableHSPort(){
SetSensorType(S4, SENSOR_TYPE_NONE);
SetHSFlags(HS_UPDATE);
SetSensorType(S4, SENSOR_TYPE_NONE);
}
So to initialize RS485, I would make a call like this: nxtEnableHSPort(baudrate); where baudrate would be e.g. 9600. Or, if I leave the baudrate parameter empty, then it wouldn't set the speed (I guess it would use whatever speed is default).
Mark,
What I did was take the ROBOTC files from DI for WPA Connect, modify them slightly, and convert them into NXC. I tried to convert them as literally as I could (with the mods), even keeping some function names. I had to write several functions that I couldn't find suitable replacements for in NXC.
The main program:
Code: Select all
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup for Wifi Sensor, Associate with a WPA Network
//
// This scrip will connect the DI Wifi sensor to a WPA network.
//
// You must replace the values of SSID and WPA_PAK
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
#define writeRawHS(X, Y) debugnxtWriteRawHS(X, Y)
//#define writeRawHS(X, Y) nxtWriteRawHS(X, Y)
// Declare the SSID and WPA_PSK we're connecting to
byte ssid[] = {'F','a','k','e',' ','N','e','t','w','o','r','k'};
byte wpa_psk[] = {'P','a','s','s','w','o','r','d'};
#include "My debug stream lib.nxc"
#include "My DI WIFI RS485.nxc"
#include "DIWIFI WPA Connect_h.nxc"
void wifi_startup(){
config_wifi(); // This function sets up the wifi sensor for operation. Basic housekeeping.
wifi_auth_mode(0); // Set the authentication mode.
// 0 is none or WPA // 1 is Open network // 2 is Shared with WEP
setDHCP(1); // Get us an IP number
set_wpa_psk(); // Calculates your psk
Wait(100);
Receive(false); // Housekeeping
Receive(false); // Housekeeping
connect_to_ssid(); // Connects to the wifi network you've designated
PlaySound(SOUND_DOUBLE_BEEP); // After connection, announce to the world you're connected.
Receive(true); // Housekeeping.
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main Task
////////////////////////////////////////////////////////////////////////////////////////////////////////
task main()
{
//bNxtLCDStatusDisplay = true; // Enable top status line display
wifi_startup(); // This is where the work is done.
PlaySound(SOUND_DOUBLE_BEEP); // Make some noise when we're connected.
PlayTone(500, 100); // Make some noise when we're connected.
}
DIWIFI WPA Connect_h.nxc:
Code: Select all
byte BytesRead[8];
const byte newline[] = {0x0D};
typedef byte buff_t;
buff_t buffer[128];
long baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600};
// This function sends the array out Port 4.
void debugnxtWriteRawHS(byte pData[], byte nLength)
{
string tmpString;
byte buff[35];
memcpy(buff, pData, nLength);
tmpString = FlattenVar(buff);
writeDebugStream(tmpString);
nxtWriteRawHS(pData, nLength);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Clear Read Buffer
// Run this to clear out the reading buffer.
// Simply sends a carriage return, then clears the buffer out.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void clear_read_buffer()
{
byte nData[] = {13};
nxtWriteRawHS(nData, 1);
Wait(1000); //100?
while(HSInputBufferInPtr()){
GetHSInputBuffer(0, 1, BytesRead); //Read the buffer
SetHSInputBufferInPtr(0);
}
GetHSInputBuffer(0, 1, BytesRead);
SetHSInputBufferInPtr(0);
Wait(10); //100?
}
/////////////////////////////////////////////////////////
//Scan Baud Rate - Scans the baud rate, sets up the sensor.
/////////////////////////////////////////////////////////
long scanBaudRate() {
byte Retried9600 = 0;
string tmpString;
byte attention[] = {'+','+','+',13};
for (int i = 0; i < 8; i++) {
Retry_9600:
byte tmpbuff[8];// = {0, 0, 0, 0, 0, 0, 0, 0};
nxtDisableHSPort();
Wait(10);
nxtEnableHSPort(baudrates[i]);
// nxtSetHSBaudRate(baudrates[i]);
clear_read_buffer();
Wait(1000);
writeDebugStreamLine("Trying %ld", baudrates[i]);
nxtWriteRawHS(attention, 4); //nxtWriteRawHS(attention, sizeof(attention));
nxtReadRawHS(tmpbuff, 7); // make sure last ubyte is always NULL
tmpString = FlattenVar (tmpbuff);
writeDebugStreamLine(tmpString);
if ((StringFind(tmpString, "ERR") > -1) ||
(StringFind(tmpString, "OK") > -1) ||
(StringFind(tmpString, "0") > -1) ||
(StringFind(tmpString, "2") > -1)) {
clear_read_buffer();
writeDebugStreamLine("Success at %ld", baudrates[i]);
writeDebugStreamLine("");
return baudrates[i];
}
writeDebugStreamLine("Failed at %ld", baudrates[i]);
if(i == 0 && Retried9600 == 0){Retried9600 = 1;goto Retry_9600;} //It seems to always pick up on it the second time, so try it again.
}
clear_read_buffer();
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Receive Bytes
// Reads whatever is in the buffer and prints to debug
////////////////////////////////////////////////////////////////////////////////////////////////////////
void Receive(bool wait=false)
{
if (wait)
while (HSInputBufferInPtr() == 0) Wait(5);
long StartTick = CurrentTick();
bool TimeOut = 0;
while (HSInputBufferInPtr() > 0) {
SetHSInputBufferInPtr(0);
StartTick = CurrentTick();
nxtReadRawHS(BytesRead, 1);
writeDebugStream("%c", BytesRead[0]);
until(HSInputBufferInPtr() > 0 || TimeOut){
if(StartTick + 100 < CurrentTick())TimeOut = 1;
}
}
}
/*int appendToBuff(byte &buf, const long index, const ubyte &pData, const long nLength)
{
if (index == 0) memset(buf, 0, sizeof(buf));
memcpy(buf[index], pData, nLength);
return index + nLength;
} */
//index = appendToBuff( buffer, index, ssid_cmd, sizeof(ssid_cmd));
int appendToBuff(byte & buf[], long index, byte pData[], long nLength)
{
if (index == 0){
for (int i = 0; i < ArrayLen(buf); i++){
buf[i] = 0;
}
}
//memcpy(buf[index], pData, nLength);
//ArraySubset(buf, pData, index, nLength);
for(int i = 0; i < nLength; i++){
buf[i + index] = pData[i];
}
return index + nLength;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Echo All Input Off - Turns off the echo effect on the wifi.
// Sending the serial command "ate0" which turns off the echo effect.
// Sends one single byte at a time, pauses.
// Drains receiver with a read each time.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void echo_all_input_off()
{
byte nData[] = {'a','t','e','0',13};
// byte s_buf[1];
// for(int i = 0; i < 5; i++){
// s_buf[0] = nData[i];
// writeRawHS(s_buf, 1); // Send the command, byte by byte.
// nxtReadRawHS(BytesRead, 8); // Clear out the echo.
// Wait(100);
// }
SetHSInputBufferInPtr(0);
writeRawHS(nData, 5);
nxtReadRawHS(BytesRead, 8);
Receive(true);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Software Flow Control On
// Send string "at&k1" and carriage return.
// Shouldn't need the wait or read now that we've got the echo off.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void software_flow_control()
{
writeDebugStreamLine("sfwr_flw_cntrl");
byte nData[] = {'a','t','&','k','1',13};
writeRawHS(nData[0], 6); // Send the command, byte by byte.
Wait(1000);
Receive(true);
// wait10Msec(100);
}
//////////////////////////////////////////////////////////////////
// Configure the verbose mode of the wifi sensor.
// n = 0, verbose disabled.
// n = 1, verbose enable.
//////////////////////////////////////////////////////////////////
void set_verbose(byte n)
{
if(n) {n = 49;} // Shouldn't be larger than 1 so set it back.
else {n = 48;}
writeDebugStreamLine("set_verbose");
byte nData[] = {'a','t','v',49,13};
// nData[3] = n;
writeRawHS(nData, 5); // Send the command, byte by byte.
Receive(true);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set the Infrastructure Mode.
// Send string "AT+WM = n" and carriage return.
// This sets the infrastructure mode as either infrastructure or ad-hoc network.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void infrastructure_mode(int state)
{
writeDebugStreamLine("wifi_infra_mode.");
char state_n = state + 48;
byte nData[] = {'a','t','+','w','m','=',0 ,13};
nData [6] = state_n;
writeRawHS(nData, 8); // Send the command, byte by byte.
Receive(true);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Disassociate from any networks.
// Send string "AT+WD" and carriage return.
// This dissaciates from any networks we're currently connected to.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void disass()
{
writeDebugStream("discon_frm_networks");
byte nData[] = {'a','t','+','w','d',13};
writeRawHS(nData, sizeof(nData)); // Send the command, byte by byte.
writeRawHS(newline, sizeof(newline)); // send new line
Receive(true);
}
void set_network_config()
{
byte wpa_psk_cmd[] = {'A','T','S','1','=','1','0','0','0'};
int index = 0;
index = appendToBuff(buffer, index, wpa_psk_cmd, sizeof(wpa_psk_cmd));
index = appendToBuff(buffer, index, newline, sizeof(newline));
writeRawHS(buffer[0], index);
Receive(true);
}
// Keep Association Alive for 20 Minutes
void Keep_Alive() {
int index = 0;
byte Keep_Alive_cmd[] = {'A','T','+','P','S','P','O','L','L','I','N','T','R','L','=','1','2','0','0'};
index = appendToBuff(buffer, index, Keep_Alive_cmd, sizeof(Keep_Alive_cmd));
index = appendToBuff(buffer, index, newline, sizeof(newline));
writeRawHS(buffer[0], index);
Receive(true);
}
void max_transmit_power() {
writeDebugStreamLine("Set Max Xmit Power");
byte status_cmd[] = {'a','t','+','W','P','=', '7', 13};
writeRawHS(status_cmd[0], sizeof(status_cmd)); // Send the command, byte by byte.
Receive(true);
}
void config_wifi(){
//It must be properly connected before continueing, so don't continue until it's communicating.
while(scanBaudRate()==0){writeDebugStreamLine("Trying again");} // This function scans the baud rate and sets up the server. You can also call the "setupHighSpeedLink" function
// if you want a specific baud rate. If the baud rate of the wifi sensor was a different rate, this will
// connect the sensor to the wifi server.
// Configure the link for raw read and write. User program will have complete control over the link.
// User program will be responsible for managing the half-duplex operation and must prevent collisions!
clear_read_buffer(); // Clear out the buffer and test TX/RX.
Wait(1000);
writeDebugStreamLine("echo_all_input_off");
echo_all_input_off(); // Turn off serial echo.
software_flow_control(); // Turn on software flow control
set_verbose(1); // Turn on verbose responses.
infrastructure_mode(0); // Setup as infrastructure. 1 would be adhoc network. 0 is infrastructure.
disass(); // Disassociate from any networks we might be hooked to.
set_network_config();
Keep_Alive(); // Keep association with network alive.
max_transmit_power(); // Max transmit power . . . rock out and forget about the batteries.
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// WIFI: Set Authentication Mode
// Security of the wifi system we're connecting to.
// Send string "at+wauth=<n>" and carriage return.
// n = 0 --> No security mode
// n = 1 --> Open security mode
// n = 2 --> Shared with WEP
////////////////////////////////////////////////////////////////////////////////////////////////////////
void wifi_auth_mode(int state)
{
writeDebugStreamLine("wifi_auth_mode");
char state_n = state + 48;
byte nData[] = {'a','t','+','w','a','u','t','h','=',48,13};
nData[9] = state_n;
writeRawHS(nData, 11); // Send the command, byte by byte.
Receive(true);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Dynamic Host Configuration Protocol
// Sends the command AT+NDHCP=<n>
// We're gong to turn it on or turn it off. This will acquire an IP address automatically.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
void setDHCP(int n)
{
writeDebugStreamLine("setDHCP");
byte dhcp_cmd[] = {'a','t','+','N','D','H','C','P', '=', 49, 13};
dhcp_cmd[9] = n + 48;
writeRawHS(dhcp_cmd, 11); // Send the command, byte by byte.
Receive(true);
Wait(1000);
}
void set_wpa_psk()
{
byte wpa_psk_cmd[] = {'A','T','+','W','P','A','P','S','K','='};
unsigned byte dummy[] = {','};
int index = 0;
writeDebugStreamLine("set_wpa_psk");
Wait(250);
writeDebugStreamLine(FlattenVar(wpa_psk_cmd));
index = appendToBuff(buffer, index, wpa_psk_cmd, sizeof(wpa_psk_cmd));
Wait(250);
writeDebugStreamLine(FlattenVar(ssid));
index = appendToBuff(buffer, index, ssid, sizeof(ssid));
Wait(250);
writeDebugStreamLine(FlattenVar(dummy));
index = appendToBuff(buffer, index, dummy, sizeof(dummy));
Wait(250);
writeDebugStreamLine(FlattenVar(wpa_psk));
index = appendToBuff(buffer, index, wpa_psk, sizeof(wpa_psk));
Wait(250);
writeDebugStreamLine(FlattenVar(newline));
index = appendToBuff(buffer, index, newline, sizeof(newline));
Wait(250);
writeRawHS(buffer, index);
}
bool Receive_connect(bool wait=false)
{
int i = 0;
byte Bytes_Error[128];
if (wait)
while (HSInputBufferInPtr() == 0) Wait(5);
while (HSInputBufferInPtr() > 0) {
nxtReadRawHS(BytesRead, 1);
writeDebugStream("%c", BytesRead[0]);
Wait(2);
Bytes_Error[i] = BytesRead[0];
i++;
}
writeDebugStream("%c", Bytes_Error[0]);
writeDebugStream("%c", Bytes_Error[1]);
writeDebugStream("%c", Bytes_Error[2]);
writeDebugStream("%c", Bytes_Error[3]);
if(Bytes_Error[2] == 'E' && Bytes_Error[3] == 'R'){
return false;
}
return true;
}
void set_ssid() {
byte ssid_cmd[] = {'A','T','+','W','A','='};
int index = 0;
index = appendToBuff(buffer, index, ssid_cmd, sizeof(ssid_cmd));
writeDebugStreamLine("1" + FlattenVar(buffer));
index = appendToBuff(buffer, index, ssid, sizeof(ssid));
writeDebugStreamLine("2" + FlattenVar(buffer));
index = appendToBuff(buffer, index, newline, sizeof(newline));
writeDebugStreamLine(FlattenVar(ssid_cmd));
writeDebugStreamLine(FlattenVar(ssid));
writeDebugStreamLine("3" + FlattenVar(buffer));
writeRawHS(buffer, index);
}
// This repeatedly tries to connect until succesful.
void connect_to_ssid(){
disass();
bool quit = false;
while(quit == false){
set_ssid();
quit = Receive_connect(true);
}
}
My DI WIFI RS485.nxc:
Code: Select all
/*
* Matthew Richardson
* matthewrichardson37<at>gmail.com
* http://mattallen37.wordpress.com/
* November 2011
*
* You may use this code as you wish, provided you give credit where it's due.
*
* This is a library of functions for low level communication with the DIWIFI.
*/
void nxtWriteRawHS(byte pData[], byte nLength)
{
string StringSendData = FlattenVar(pData); //Flatten it into a string
SendRS485String(StringSendData); //Send the string
until(HSOutputBufferOutPtr() == StrLen(StringSendData)+1); //Wait until the string has been sent
}
int nxtReadRawHS (byte & tmpbuff[], byte nLength, long TimeOut = 1000){
long OriginalTick = CurrentTick();
until(HSInputBufferInPtr()>=1){
if (OriginalTick + TimeOut < CurrentTick()){
PlayTone(2500, 10);
Wait(10);
return -3; //Didn't get anything
}
}
OriginalTick = CurrentTick();
until(HSInputBufferInPtr()>=nLength+1){
if (OriginalTick + TimeOut < CurrentTick()){
byte Nlength = HSInputBufferInPtr();
GetHSInputBuffer(0, Nlength, tmpbuff);
SetHSInputBufferInPtr(0);
PlayTone(440, 100);
Wait(100);
return -2; //Got something, but not full length
}
}
GetHSInputBuffer(0, nLength, tmpbuff);
SetHSInputBufferInPtr(0);
return 1; //It was full length, and good
}
/*
int nxtReadRawHS (byte & tmpbuff[], byte nLength, long TimeOut = 1000){
long OriginalTick = CurrentTick();
until(HSInputBufferInPtr()>=nLength+1){
if (OriginalTick + TimeOut < CurrentTick()){
return -2;
}
}
GetHSInputBuffer(0, nLength, tmpbuff);
SetHSInputBufferInPtr(0);
return 1;
}
*/
void nxtSetHSBaudRate(long baudrate){
switch (baudrate){
case 9600:
SetHSSpeed(HS_BAUD_9600);
break;
case 19200:
SetHSSpeed(HS_BAUD_19200);
break;
case 38400:
SetHSSpeed(HS_BAUD_38400);
break;
case 57600:
SetHSSpeed(HS_BAUD_57600);
break;
case 115200:
SetHSSpeed(HS_BAUD_115200);
break;
case 230400:
SetHSSpeed(HS_BAUD_230400);
break;
case 460800:
SetHSSpeed(HS_BAUD_460800);
break;
case 921600:
SetHSSpeed(HS_BAUD_921600);
break;
}
}
void nxtDisableHSPort(){
SetSensorType(S4, SENSOR_TYPE_NONE);
SetHSFlags(HS_UPDATE);
SetSensorType(S4, SENSOR_TYPE_NONE);
}
void nxtEnableHSPort(long baudrate = 0){
SetSensorType(S4, SENSOR_TYPE_HIGHSPEED);
SetHSFlags(HS_UPDATE);
SetHSState(HS_INITIALISE);
SetHSFlags(HS_UPDATE);
if (baudrate) nxtSetHSBaudRate(baudrate);
SetHSFlags(HS_UPDATE);
}
My debug stream lib.nxc:
Code: Select all
/*
* Matthew Richardson
* matthewrichardson37<at>gmail.com
* http://mattallen37.wordpress.com/
* November 20, 2011
*
* You may use this code as you wish, provided you give credit where it's due.
*
* This is a library of functions for creating a debug stream on the NXT LCD.
*/
int StringFind(string In_String, string F_String){ // Input a string to look through, a string to look for, and return the position
if (StrLen(In_String)<StrLen(F_String)) return -2; // The input string is shorter than the string I am looking for, so return -2
for (int i = 0; i < StrLen(In_String); i++){ // repeat for the number of times the input string is long
if (In_String[i]==F_String[0]){ // If the current char is the same as the first char in the string to look for
for (int ii = 0; ii < StrLen(F_String); ii++){ // Repeat for the number of times the find string is long
if (In_String[i+ii]!=F_String[ii]) goto LookForFirstChar; // If the chars don't match up, go back to looking for the first char again
}
return i; // It found the matching string, so return the start char position 0 - n
}
LookForFirstChar: // Label to jump to to look again for the first char of the string to search for
}
return -1; // It didn't find the string, so return -1
}
byte sizeof(byte buf[]){ // Strictly for added compatibility with ROBOTC
return ArrayLen(buf);
}
string LCD_LINE_ONE;
string LCD_LINE_TWO;
string LCD_LINE_THREE;
string LCD_LINE_FOUR;
string LCD_LINE_FIVE;
string LCD_LINE_SIX;
string LCD_LINE_SEVEN;
string LCD_LINE_EIGHT;
byte LCD_COL_POS = 1;
void GetNewLine(){ // Get a new line by shifting everything up a line and clearing the necessary string and variable
LCD_LINE_ONE = LCD_LINE_TWO ;
LCD_LINE_TWO = LCD_LINE_THREE;
LCD_LINE_THREE = LCD_LINE_FOUR ;
LCD_LINE_FOUR = LCD_LINE_FIVE ;
LCD_LINE_FIVE = LCD_LINE_SIX ;
LCD_LINE_SIX = LCD_LINE_SEVEN;
LCD_LINE_SEVEN = LCD_LINE_EIGHT;
LCD_LINE_EIGHT = "";
LCD_COL_POS = 1;
}
void writeDebugTextAdv(string txt, bool NL){ // Post text to the LCD, and optionally get a new line first
if (NL){ // If I requested to get a new line (start with an empty line)...
GetNewLine(); // ...Get a new line.
}
if (LCD_COL_POS - 1 + StrLen(txt) - 1 >= 16){ // If it won't all fit on the current line
unsigned int cur_txt_char = 0;
char txt_char[]; // Create an array to hold the input text for easy manipulation
const unsigned int txt_len = StrLen(txt);
ArrayInit (txt_char, 0, txt_len); // Set the size to the length of the input text
UnflattenVar (txt, txt_char); // Put the input text string into the array
char LCD_LINE_EIGHT_char[16]; // Create an array to hold the line I am building
char LCD_LINE_EIGHT_char_temp[]; // Create an array to hold the existing charactors of the current line
const unsigned int LCD_LINE_EIGHT_char_temp_len = StrLen(LCD_LINE_EIGHT);
ArrayInit (LCD_LINE_EIGHT_char_temp, 0, LCD_LINE_EIGHT_char_temp_len); // Initialize the array with the right number of elements
UnflattenVar (LCD_LINE_EIGHT , LCD_LINE_EIGHT_char_temp); // Put the previous text into array format
for (int i = 0; i < LCD_LINE_EIGHT_char_temp_len; i++){ // Repeat for the number of times it takes to copy all the previous chars into the new char array
LCD_LINE_EIGHT_char[i] = LCD_LINE_EIGHT_char_temp[i]; // In the properly lengthed array
}
for (int i = 0; i < (17-LCD_COL_POS); i++){ // repeat once for every char to add to the line
LCD_LINE_EIGHT_char[i+LCD_COL_POS-1] = txt_char[i];
cur_txt_char++;
}
LCD_LINE_EIGHT = FlattenVar(LCD_LINE_EIGHT_char); // The line is full, so go ahead and convert it into the string...
GetNewLine(); // ...and grab a new line...
ArrayInit (LCD_LINE_EIGHT_char, 0, 16); // ...and clear the values of the current line array to 0
unsigned int NumberOfFullLines = (txt_len - cur_txt_char - 1) / 16; // Determine how many full lines of chars there are left
if(NumberOfFullLines){ // If there are some (at least one)...
repeat(NumberOfFullLines){ // Repeat for the number of full lines needing to be written
unsigned int iiii = 0;
repeat(16){ // Repeat 16 times (once for each char).
LCD_LINE_EIGHT_char[iiii] = txt_char[cur_txt_char];
iiii++;
cur_txt_char++;
}
LCD_LINE_EIGHT = FlattenVar(LCD_LINE_EIGHT_char); // The array is full, so write it to the string...
GetNewLine(); // ...and get a new line...
ArrayInit (LCD_LINE_EIGHT_char, 0, 16); // ...and set the array values back to 0
}
}
byte ii=0;
if(txt_len - cur_txt_char < 17){ // if there are less than 17 chars left (not more than a whole line) then continue
repeat(txt_len - cur_txt_char){ // Repeat once for every char that needs to be on the last line
LCD_LINE_EIGHT_char[ii] = txt_char[cur_txt_char];
ii++;
cur_txt_char++;
}
}
else // If there were 17 or more, then an error occured
{
PlayTone(500, 100);
Wait(500);
}
ArrayInit (LCD_LINE_EIGHT_char_temp, 0, ii); // Initialize the array with an element for each char in the last line
byte iii=0;
repeat(ii){ // Repeat once for every char that needs to be added to the last line
LCD_LINE_EIGHT_char_temp[iii] = LCD_LINE_EIGHT_char[iii];
iii++;
}
LCD_LINE_EIGHT = FlattenVar(LCD_LINE_EIGHT_char_temp); // Write the string to the values in the array
LCD_COL_POS = ii; // Set the pointer to the proper place for furute use
}
else{ // Otherwise, if it will all fit on the current line...
LCD_LINE_EIGHT += txt; // Just add to the current string
}
LCD_COL_POS = StrLen(LCD_LINE_EIGHT) + 1; // Set the pointer for use later
asm{
acquire __PointOutMutex // Clear the screen
mov __PointOutArgs.Location.X, 200
mov __PointOutArgs.Location.Y, 200
mov __PointOutArgs.Options, __constVal1
syscall 14, __PointOutArgs
release __PointOutMutex
acquire __TextOutMutex
mov __TextOutArgs.Location.X, 0
set __TextOutArgs.Options, 0
mov __TextOutArgs.Location.Y, 56
mov __TextOutArgs.Text, LCD_LINE_ONE
syscall 13, __TextOutArgs // Display the first...
mov __TextOutArgs.Location.Y, 48
mov __TextOutArgs.Text, LCD_LINE_TWO
syscall 13, __TextOutArgs // ...second...
mov __TextOutArgs.Location.Y, 40
mov __TextOutArgs.Text, LCD_LINE_THREE
syscall 13, __TextOutArgs // ...third...
mov __TextOutArgs.Location.Y, 32
mov __TextOutArgs.Text, LCD_LINE_FOUR
syscall 13, __TextOutArgs // ...fourth...
mov __TextOutArgs.Location.Y, 24
mov __TextOutArgs.Text, LCD_LINE_FIVE
syscall 13, __TextOutArgs // ...fifth...
mov __TextOutArgs.Location.Y, 16
mov __TextOutArgs.Text, LCD_LINE_SIX
syscall 13, __TextOutArgs // ...sixth...
mov __TextOutArgs.Location.Y, 8
mov __TextOutArgs.Text, LCD_LINE_SEVEN
syscall 13, __TextOutArgs // ...seventh...
mov __TextOutArgs.Location.Y, 0
mov __TextOutArgs.Text, LCD_LINE_EIGHT
syscall 13, __TextOutArgs // ...and eighth lines of text
release __TextOutMutex
}
}
void writeDebugText(string txt, bool NL){
static int LCD_LINE = 1;
static int LCD_COL = 0;
if(NL){
LCD_LINE++;
LCD_COL = 0;
}
if(LCD_LINE>8){
LCD_LINE = 1;
LCD_COL = 0;
ClearScreen();
}
TextOut(LCD_COL * 6, LCD_LINE1 + 8 - (LCD_LINE*8), txt);
LCD_COL+=StrLen(txt);
}
void writeDebugStream(string in_txt, float display_f = 0, bool NL = 0){
string String_out;
int Formatter_offset = StringFind(in_txt,"%");
if (Formatter_offset > -1){ //If there is a formatter
char in_txt_char[];
const unsigned int in_txt_len = StrLen(in_txt);
ArrayInit (in_txt_char, 0, in_txt_len);
UnflattenVar (in_txt, in_txt_char);
byte Formatter_Length = in_txt_len - Formatter_offset;
char formatter_char[];
ArraySubset(formatter_char, in_txt_char, Formatter_offset, Formatter_Length);
char dis_txt_char[];
const unsigned int dis_txt_len = in_txt_len - Formatter_Length;
ArraySubset(dis_txt_char, in_txt_char, 0, dis_txt_len);
string formatter = FlattenVar(formatter_char);
if(StringFind(formatter,"f")!=-1){
sprintf(String_out, formatter, display_f);
}
else{
long display_i = display_f;
sprintf(String_out, formatter, display_i);
}
String_out = FlattenVar(dis_txt_char) + String_out;
}
else{
String_out = in_txt;
}
writeDebugTextAdv(String_out, NL);
}
void writeDebugStreamLine(string in_txt, float display = 0){
writeDebugStream(in_txt, display, 1);
}
Please note that ATM I have no idea what comments apply, and due to some more pressing issues involving family, I am unable to access an NXT and my normal computer for probably another week or so (so no testing for me for a while).
So, at one point I said:
At this point in my testing, I think it might be that 9600 baud in NXC isn't truly 9600. Another theory of mine is that the FW throws on a header to all strings being sent over RS485. It would make sense to me how two NXTs do fine, but the DIWIFI gets jammed. Anyhow, both of those are just suspicions which I can't test without an NXT and an RS485 to TTL UART converter (plus a computer and terminal), of which I don't have access to right now.
Based on what little I know of how the RS485 part of the FW works, I am not ready to rule out either of those possibilities (Edit: I guess maybe the speed thing is a little impossible). What now seems just as likely though, is that the DIWIFI is echoing back everything, jamming the half-duplex RS485 stream (not allowing itself to see the command turning off echo). If somehow the timing of ROBOTC's RS485 is different, that could be why we are getting the results we are.
When I get home, I will test out this theory (turn off echo with ROBOTC, and then switch over to NXC). If it proves to be the problem, I can think of several possible HW fixes.