Custom Controller?

Alright, I changed the speed from 9600 to 115200, and it seems to be working better, besides the fact that there is a few random variables. Does anyone know why those few random variables are in the stream?

EDIT: Over time, it seems like it slows down.

I added a little filter, that look at the input from the Vex, and if it isn’t a 1 or a 0, it skips past it. It seems almost instantly transmitted. If I were going to send multiple variables and store them on each end, how would I do that. Right now, this is only one variable.

Arduino:

#include <SoftwareSerial.h>
SoftwareSerial Serial2(10, 11); // RX, TX

int pot=127;
int light=1;

void setup(){
   //Serial.begin(9600);
   Serial2.begin(115200);
   pinMode(13, OUTPUT);
}

void loop(){
    if (Serial2.available() > 0) {
      light=Serial2.read();
    }
    if (light==0 || light==1){
      if (light==0){
        digitalWrite(13, HIGH);
      }else if(light!=0){
        digitalWrite(13, LOW);
      }
    }
    pot=analogRead(A0);
    pot=map(pot,0,1023,0,255);
    Serial2.write(pot);
    //Serial.println(light);
    delay(16);
}

Vex:

// everything.c : implementation file
#include "API.h"

// TODO: add user code here

//#include "Main.h"

void stuff ( void )
{
      unsigned char tx = 0; // Byte to be transmitted
      //unsigned char rx = 0; // Byte we received
      unsigned long rx_count = 0; // Count of bytes received
      unsigned long tx_count = 0; // Count of bytes sent

      int switchD1=0; //1 not clicked, 0 clicked
      int potentiometer=127; //Value from arduino

      // First, set up the RX/TX Port for use 
      OpenSerialPortTwo ( BAUD_115200 ) ; // Select your baud rate here

      while(1){
            while(GetSerialPort2ByteCount()){
                  potentiometer=ReadSerialPortTwo();
            }
            switchD1 = GetDigitalInput(1); // Get the switch
            WriteSerialPortTwo(switchD1);
            SetPWM(1, potentiometer); // Set motor 1 to the potentiometer value
            Wait ( 16 ) ; 
      }
}

If I wanted to add another button, how would I send that over to the Arduino, and have it correctly identify each button and light the correct led?

Alright, I added another button to the Vex, and I got that to work. Button one will add 1 to the variable it will send, and button 2 will add a 2 to the variable to send. It they are both pressed, the Arduino receives a 3.

Does anyone know Arduino and Vex code? See I need to send variables. My example: One 2 axis joystick and four buttons. Someone on the Arduino forum suggested using for the protocal, so how would I do that on Arduino, and receive it on Vex?

First off for sending it. How would you send ? xxxx is the x axis of the joystick, so it needs to be 4 digits total all the time, same for y. a b c and d are the buttons. So I am wondering how you can send it.

Then there is receiving the data on the Vex Pic. How would you receive the data and put it into variables that I can use for my programs?

That wouldn’t be the full protocal, but it would be enough to get me started on making a bigger one to support more controls.

There is quite a few way this can be done… The Simplest and most Verbose is to send it just the way you described above:

For Instance, if X=595 and Y=843 , and Button A and D are Pressed, you would send one Line of Text, followed by a Carriage Return, like this:
<0595 0843 1 0 0 1\n>

Numbers are represented between 0000 and 1023 and the Buttons are 0 or 1.

This is a Fixed Length Data Record, because the each Item ( field ) is the same length so the Entire Record is the Same Length from one Record to the next.


On the Arduino Side, you need to Convert the Analog Value to a string, just like you are going to display it, but send it to the PIC, the same for the PIC Side when returning the State of the Switches…

on the PIC, I use the sprintf() function, which is a C Library function that should be available on the Arduino too…

===============================================

More speed-effective, but more complicated to trouble-shoot is to leave the Values in Binary and send them between the two devices…

sprintf does work great. Another user on a different forum suggested that to. When I send it over to the Vex Pic, it all comes in as ascii, each character on its own line. Is there some way I can convert it back to a string and decode it into the same variables?

I am in a hurry, but here is a few things…

Yes, this is an ASCII String, but each char is on its own line?? How are you sending the String?? You can work with a Line for each Variable, and the overall length might not be much different than the method I am promoting, but there are a few other subtle things that the method I am suggesting provides…

There are a a few Rules ( collected from the Embedded Programming World ), but one of the most valuable that I have found is:
**All Data, from Sensors and External Sources, Must be Sanitized!!! **

You don’t want you “system” to go craze, because it acted on Bad Data, that a Simple Check would have eliminated… Know the Range of your Intended Data, and check them…

<0595 0843 1 0 0 1\n>

The New Line is an End Of Record marker. If you start reading in the middle of a Data Stream, you Ignore all data until you reach the New Line, then, since your Records are Fixed Length, you read your Data Stream until the next New Line.

The Distance from One New Line to the Next should always be the same. ( The above Record is 18, or 19 if the New Line is both a Carriage Return and a New Line, it doesn’t matter much, because neither the Carriage Return or the New Line is part of your Data, it merely divides One Data Record from the Next)

If the Number of Bytes in your Record match the Right Number, there is a Good Chance, you have a Good Record.

Now you also know the length of each Data Item, ( Field ) within the Record, and where it is suppose to start ( and stop ). For instance, the X Position should be Bytes Zero to Three, with a Space in Position Four ( Remember that Arrays in C, C++ and Java start at Zero ), the Y Position should be Bytes Five to Eight , with a Space in Position Nine, and so on.

There is a lot of different ways to break these out, but a Brut Force way with limited checks and lots of room for improvement would be ( With a bunch of possible errors ;)… ):



#include <string.h>

 int switchD1=0; //1 not clicked, 0 clicked
 int switchD2=0; //1 not clicked, 0 clicked
 int switchD3=0; //1 not clicked, 0 clicked
 int switchD4=0; //1 not clicked, 0 clicked
 
 int potentiometer_X=127; //Value from arduino
 int potentiometer_Y=127; //Value from arduino
 
 char Good_Record = 1;	/*	True/False	*/
 
 
 int parse_data_record(char data_record])
 {
	int loop1, loop2, x, y;
	char buffer[10];
	
	
	/*	Parse X Value	*/
	for(loop1=0, loop2=0; loop <4; loop1++, loop2++)
	{
		buffer[loop2] = data_record[loop1];
	}
	
	buffer[loop1] = '\x0';	/*	String Terminator	*/
	potentiometer_X = atoi(buffer);
 
	/*	Check for Valid Number and Range	*/
	if ( potentiometer_X > -127 && potentiometer_X < 128)
	{
		continue;	/*	STILL TRUE	*/
	}
	else
	{
		Good_Record = 0;	/*	FALSE	*/
	}
	
	/*	Parse Y Value	*/
	for(loop1=5, loop2=0; loop <9; loop1++, loop2++)
	{
		buffer[loop2] = data_record[loop1];
	}
	
	buffer[loop1] = '\x0';	/*	String Terminator	*/
	potentiometer_Y = atoi(buffer);
 
	/*	Check for Valid Number and Range	*/
	if ( potentiometer_Y > -127 && potentiometer_Y < 128)
	{
		continue;	/*	STILL TRUE	*/
	}
	else
	{
		Good_Record = 0;	/*	FALSE	*/
	}
	
	/*	Check D1 Value	*/
	buffer[0] = data_record[10];	/*	D1	*/
	buffer[1] = '\x0';	/*	String Terminator	*/
	switchD1 = atoi(buffer);
 
	/*	Check for Valid Number and Range	*/
	if ( switchD1 > -1 && switchD1 < 2)
	{
		continue;	/*	STILL TRUE	*/
	}
	else
	{
		Good_Record = 0;	/*	FALSE	*/
	}

	/*	Check D2 Value	*/
	buffer[0] = data_record[12];	/*	D2	*/
	buffer[1] = '\x0';	/*	String Terminator	*/
	switchD2 = atoi(buffer);
 
	/*	Check for Valid Number and Range	*/
	if ( switchD2 > -1 && switchD2 < 2)
	{
		continue;	/*	STILL TRUE	*/
	}
	else
	{
		Good_Record = 0;	/*	FALSE	*/
	}

	/*	Check D3 Value	*/
	buffer[0] = data_record[14];	/*	D3	*/
	buffer[1] = '\x0';	/*	String Terminator	*/
	switchD3 = atoi(buffer);
 
	/*	Check for Valid Number and Range	*/
	if ( switchD3 > -1 && switchD3 < 2)
	{
		continue;	/*	STILL TRUE	*/
	}
	else
	{
		Good_Record = 0;	/*	FALSE	*/
	}
		
	/*	Check D4 Value	*/
	buffer[0] = data_record[16];	/*	D4	*/
	buffer[1] = '\x0';	/*	String Terminator	*/
	switchD1 = atoi(buffer);
 
	/*	Check for Valid Number and Range	*/
	if ( switchD4 > -1 && switchD4 < 2)
	{
		continue;	/*	STILL TRUE	*/
	}
	else
	{
		Good_Record = 0;	/*	FALSE	*/
	}
	
	return ( Good_Record );
 }


If all 6 Data Items are Numbers and in the Correct Range, parse_data_record(char data_record]) will return a ‘1’, indicating you can process this Record’s Data. You could still have Incorrect Data, but not Bad Data.

The above code can be improved a lot, this is a poor example, written in 35 min…

So do I still do parse_data_record(); from the drag and drop gui? How do you remove the gui and use just the code? I am using EasyC Pro.

I also have another question. This sprintf(buffer, “<%d %d %d %d %d>”, x, y, a, b, c); works to put it into , but how can I add zeros infront of x and y to make it a four digit number?

Start googling

to print with leading zeros use, for example, %04d.

printf(“%04d”, 12);

prints

0012

That is what the other guy on the other forum said, but he said sprintf, not printf. The same thing following to.

Options–>Add New File to Project

Remember that you will need to Load a string with the Data Record that starts with the X Position in the First Byte… That means that you will need another Function to Read the Data Stream, until the New Line is encountered and then read 18 or 19 or so bytes until the next New Line, then send those 18 bytes to the parse_data_record() function.

I have seen this done with a Worst Case Buffer, something like 2 times the Record size, and you read into it, until the Second New Line is found, then Copy from the Character after the First New Line to the Second New Line, and send that to the parse data function, IF the length is 18 ( or 19 ). If it is longer or shorter, there is no way the Data is Good…

There are a lot of improvements that should be done to the above function, such as the variable are loaded one at a time, even if there is No or Bad Data… One Improvement would be to Parse and Store the Data Locally, in the parse_data_record(), then when you think its Good Data, Copy it to the Main Variables.

Also, using atoi() is overkill for One Character… A better check would be:



	/*	Check D1 Value	*/
	buffer[0] = data_record[10];	/*	D1	*/
 
	/*	Check for Valid Number and Range	*/
	if ( buffer[0] >= '0' && buffer[0] <= '9')
	{
	switchD1 = (int) buffer[0]-'0';	/*	STILL TRUE	*/
	}
	else
	{
		Good_Record = 0;	/*	FALSE	*/
	}





Actually placing all the Record Data in a Structure would be better yet, with similar Data in an Array…

How much ‘C’, C++ or Java do you know??? I have been programming in ‘C’ since 1988… C++ since 1995 ( maintenance of existing code) and Java for a Couple Years…

Sorry for not replying to that. Well, probably nothing, besides what I have picked up on with Vex and Arduino. I have programmed other languages to, mainly HTML, PHP, and CSS.

printf, sprintf, vprintf, fprintf, are all variations of printf… Formatting of One follows the others… In fact the Open Watcom compiler has One Function to handle all the formatting for all the above functions, they are Wrappers for the individual functions…

printf doesn’t error anything when I upload it, but instead of 1023, I see 0. I will try some things in the morning.

Well, prepare to get Weird… ‘C’ ( and C++ and Java ) allow you to do so much Weird Stuff, they have a contest… *The International Obfuscated C Code Contest *

IF you think what we are showing you is hard, check out the link above…

At least, Find yourself:
The C programming Language
By Brian W. Kernighan and Dennis M. Ritchie.

Published by Prentice-Hall in 1988

ISBN 0-13-110362-8 (paperback)
ISBN 0-13-110370-9

This will show you how ‘C’ works, compared to other languages…

Post your Code…

If you are going to stay with a protocol based around ASCII characters rather than a binary protocol then you may wish to surround the message with unique non printing characters. Traditionally STX (0x02), start of transmission and ETX (0x03), end of transmission were used. These are easy to detect when all the other message characters are in the range 0x20 to 0x7F.

If you decide on a binary protocol, consider one that uses a unique header. One such example is the VEX packet protocol, variations of which are used throughout the VEX product line.

Am I using ASCII? What is the difference compared to binary?

Do you think I could port the Arduino EasyTransfer library over to Vex Pic?