Asked — Edited

Vr Options?

Does anyone know if the SDK of the Oculus Rift package would work with EZB if there was a plug in developed for it? It doesn't really need to be something as big and bulky as that. Very unfortunate that Vuzix is no longer offering support with EZB. That would work great.

Like the Vuzix, I'd like to pull from the IMU data to move servos and transfer the camera feed from the EZ camera to the goggles over two complete separate computers in different places.

Any ideas or suggestions on how to POC this, would be grateful.


ARC Pro

Upgrade to ARC Pro

Subscribe to ARC Pro, and your robot will become a canvas for your imagination, limited only by your creativity.

PRO
Synthiam
#25  

Nice!

Are there any libraries that the unity asset came with? Other than the code you posted. Because if it communicates to an addition over serial, I can easily replicate

PRO
USA
#26  

Yes:

Here is an image with all the libs. I will add them one by one to follow on code format:

User-inserted image

PRO
USA
#27  
/*
  Ardunity.cpp - Ardunity Arduino library
  Copyright (C) 2015 ojh6t3k.  All rights reserved.
*/


//******************************************************************************
//* Includes
//******************************************************************************

#include "Ardunity.h"
#include "HardwareSerial.h"

extern "C" {
#include <string.h>
#include <stdlib.h>
}

//#define DEBUG_ARDUNITYAPP

//******************************************************************************
//* Constructors
//******************************************************************************

ArdunityAppClass::ArdunityAppClass()
{	
	firstController = 0;
    connected = false;
    timeoutMillis = 5000; // default timeout
}

//******************************************************************************
//* Public Methods
//******************************************************************************

void ArdunityAppClass::begin()
{
	commSocket = 0;
    bypassSocket = 0;
	readyReceived = false;
    bypassProcessUpdate = 0;
	processUpdate = 0;
    connected = false;
	Reset();
    
#ifdef DEBUG_ARDUNITYAPP
    Serial.begin(9600);
    Serial.println("\nDebug ArdunityApp");
#endif
}

void ArdunityAppClass::begin(long speed)
{
	begin();
	Serial.begin(speed);
	commSocket = (Stream*)&Serial;
	
	commSocket->write(CMD_RESET);
    commSocket->flush();
}

void ArdunityAppClass::begin(Stream *s)
{
	begin();
	commSocket = s;

	commSocket->write(CMD_RESET);
    commSocket->flush();
}

void ArdunityAppClass::begin(Stream *s, Stream *s1)
{
    begin();
    commSocket = s;
    bypassSocket = s1;
    
    commSocket->write(CMD_RESET);
    commSocket->flush();
}

void ArdunityAppClass::resolution(int pwm, int adc)
{
#if defined(__SAM3X8E__) || defined(_VARIANT_ARDUINO_ZERO_) // only DUE or ZERO
	maxPWM = pwm - 1;
	int bit = 0;
	int value = maxPWM;
	while(value > 0)
	{
		value = (int)(value >> 1);
		bit++;
	}
    analogWriteResolution(bit);
    
    maxADC = adc - 1;
	bit = 0;
	value = maxADC;
	while(value > 0)
	{
		value = (int)(value >> 1);
		bit++;
	}
    analogReadResolution(bit);    
#else
	maxPWM = 255;
	maxADC = 1023;
#endif	
}

void ArdunityAppClass::timeout(unsigned long millisec)
{
	timeoutMillis = millisec;
}

void ArdunityAppClass::process(void)
{
	process(commSocket);
}

void ArdunityAppClass::process(Stream *s)
{
	ArdunityController* controller;
	Stream *backup = commSocket;
	commSocket = s;

	if(commSocket != 0)
	{
		while(commSocket->available() > 0)
		{
			byte bit = 1;
			int inputData = commSocket->read(); // this is 'int' to handle -1 when no data

			if(inputData >= 0)
			{
				if(inputData & 0x80)
				{
					if(inputData == CMD_PING)
					{
#ifdef DEBUG_ARDUNITYAPP
                        Serial.println("RX:CMD_PING");
#endif
						commSocket->write(CMD_PING);
                        commSocket->flush();
#ifdef DEBUG_ARDUNITYAPP
                        Serial.println("TX:CMD_PING");
#endif
					}
					else if(inputData == CMD_START)
					{
#ifdef DEBUG_ARDUNITYAPP
                        Serial.println("RX:CMD_START");
#endif
                        connected = true;
                        preTime = millis();

						if(startCallback != 0)
							(*startCallback)();
                        
						controller = firstController;
						while(controller != 0)
						{
							controller->start();
							controller = controller->nextController;
						}
                        
                        if(bypassSocket != 0)
                        {
                            bypassSocket->write(CMD_START);
                            bypassSocket->flush();
                        }
                        
						commSocket->write(CMD_READY);
                        commSocket->flush();
#ifdef DEBUG_ARDUNITYAPP
                        Serial.println("TX:CMD_READY");
#endif
					}
					else if(inputData == CMD_EXIT)
					{
#ifdef DEBUG_ARDUNITYAPP
                        Serial.println("RX:CMD_EXIT");
#endif
                        connected = false;
                        
						controller = firstController;
						while(controller != 0)
						{
							controller->stop();
							controller = controller->nextController;
						}
                        
                        if(bypassSocket != 0)
                        {
                            bypassSocket->write(CMD_EXIT);
                            bypassSocket->flush();
                        }

						if(exitCallback != 0)
							(*exitCallback)();
					}
					else if(inputData == CMD_READY)
					{
#ifdef DEBUG_ARDUNITYAPP
                        Serial.println("RX:CMD_READY");
#endif
						readyReceived = true;
                        preTime = millis();
                        
                        if(bypassSocket != 0)
                        {
                            bypassSocket->write(CMD_READY);
                            bypassSocket->flush();
                        }
                    }
					else if(inputData == CMD_EXECUTE)
					{
#ifdef DEBUG_ARDUNITYAPP
                        Serial.println("RX:CMD_EXECUTE");
#endif
						if(processUpdate > 0)
						{
							controller = firstController;
							while(controller != 0)
							{
								controller->execute();
								controller = controller->nextController;
							}
                            
							processUpdate = 0;
						}
                        
                        if(bypassSocket != 0)
                            bypassSocket->write(CMD_EXECUTE);
					}
			
					if(inputData == CMD_UPDATE)
                    {
#ifdef DEBUG_ARDUNITYAPP
                        Serial.println("RX:CMD_UPDATE");
#endif
						processUpdate = 1;
                        
                        if(bypassSocket != 0)
                            bypassSocket->write(CMD_UPDATE);
                    }
					else
                    {
#ifdef DEBUG_ARDUNITYAPP
                        if(inputData >= CMD_UNKNOWN)
                        {
                            Serial.print("RX:Unknown (");
                            Serial.print(inputData);
                            Serial.println(")");
                        }
#endif
						Reset();
                    }
				}
				else if(processUpdate > 0)
				{
					if(processUpdate == 1)
					{
						ID = inputData;
						processUpdate = 2;
					}
					else if(processUpdate == 2)
					{
						numData = inputData;
						if(numData > MAX_ARGUMENT_BYTES)
							Reset();
						else
						{
							processUpdate = 3;
							currentNumData = 0;
						}
					}
					else if(processUpdate == 3)
					{
						if(currentNumData < numData)
							storedData[currentNumData++] = inputData;

						if(currentNumData >= numData)
						{
							// Decoding 7bit bytes
							numData = 0;
							for(int i=0; i<currentNumData; i++)
							{
								if(bit == 1)
								{
									storedData[numData] = storedData[i] << bit;
									bit++;
								}
								else if(bit == 8)
								{
									storedData[numData++] |= storedData[i];
									bit = 1;
								}
								else
								{
									storedData[numData++] |= storedData[i] >> (8 - bit);
									storedData[numData] = storedData[i] << bit;
									bit++;
								}
							}

							currentNumData = 0;
						
							controller = firstController;
							while(controller != 0)
							{
								if(controller->update(ID) == true)
									break;
								controller = controller->nextController;
							}
						
							processUpdate = 1;
						}
					}
                    
                    if(bypassSocket != 0)
                        bypassSocket->write(inputData);
				}
				else
					Reset();
			}
		}
        
        if(bypassSocket != 0)
        {
            while(bypassSocket->available() > 0)
            {
                int inputData = bypassSocket->read(); // this is 'int' to handle -1 when no data
                if(inputData >= 0)
                {
                    if(inputData & 0x80)
                    {
                        if(inputData == CMD_UPDATE)
                        {
                            if(readyReceived == true)
                            {
#ifdef DEBUG_ARDUNITYAPP
                                Serial.println("TX:CMD_UPDATE");
#endif
                                commSocket->write(CMD_UPDATE);
                                
                                controller = firstController;
                                while(controller != 0)
                                {
                                    controller->flush();
                                    controller = controller->nextController;
                                }
                            }
                            bypassProcessUpdate = 1;
                        }
                        else if(inputData == CMD_EXECUTE)
                        {
                            if(readyReceived == true)
                            {
#ifdef DEBUG_ARDUNITYAPP
                                Serial.println("TX:CMD_EXECUTE");
                                Serial.println("TX:CMD_READY");
#endif
                                commSocket->write(CMD_EXECUTE);
                                commSocket->write(CMD_READY);
                                commSocket->flush();
                                readyReceived = false;

                            }
                            bypassProcessUpdate = 0;
                        }
                        else
                            bypassProcessUpdate = 0;
                    }
                    else if(bypassProcessUpdate == 1)
                    {
                        if(readyReceived == true)
                            commSocket->write(inputData);
                    }
                    else
                        bypassProcessUpdate = 0;
                }
            }
        }
        else
        {
            if(readyReceived == true)
            {
#ifdef DEBUG_ARDUNITYAPP
                Serial.println("TX:CMD_UPDATE");
#endif
                commSocket->write(CMD_UPDATE);
                
                controller = firstController;
                while(controller != 0)
                {
                    controller->flush();
                    controller = controller->nextController;
                }
#ifdef DEBUG_ARDUNITYAPP
                Serial.println("TX:CMD_EXECUTE");
                Serial.println("TX:CMD_READY");
#endif
                commSocket->write(CMD_EXECUTE);
                commSocket->write(CMD_READY);
                commSocket->flush();
                readyReceived = false;
            }
        }
	}

	commSocket = backup;

	controller = firstController;
	while(controller != 0)
	{
		controller->process();				
		controller = controller->nextController;
	}
    
    if(connected)
    {
        unsigned long curTime = millis();
        if(curTime >= preTime) // if overflow then skip
        {
            if((curTime - preTime) > timeoutMillis) // check timeout
            {
                connected = false;
                
                controller = firstController;
                while(controller != 0)
                {
                    controller->stop();
                    controller = controller->nextController;
                }
            }
        }
        else
            preTime = curTime;
    }
}

void ArdunityAppClass::select(byte id) 
{
	commSocket->write(id & 0x7F);
	numArgument = 0;
}

void ArdunityAppClass::flush() 
{
	float a = numArgument / 7;
	float b = numArgument % 7;
	byte addedNum = (byte)a;
	if(b > 0)
		addedNum++;

	commSocket->write((numArgument + addedNum) & 0x7F);
	// Encoding 7bit bytes
	byte bit = 1;
	byte temp = 0;
	for(byte i=0; i<numArgument; i++)
	{
		commSocket->write((temp | (storedArgument[i] >> bit)) & 0x7F);
		if(bit == 7)
		{
			commSocket->write(storedArgument[i] & 0x7F);
			bit = 1;
			temp = 0;
		}
		else
		{
			temp = storedArgument[i] << (7 - bit);
			if(i == (numArgument - 1))
				commSocket->write(temp & 0x7F);
			bit++;
		}		
	}
}

void ArdunityAppClass::attachController(ArdunityController* controller)
{
	ArdunityController* c = firstController;
	while(true)
	{
		if(c == 0)
		{
			firstController = controller;
			break;
		}
		if(c->nextController == 0)
		{
			c->nextController = controller;
			break;
		}

		c = c->nextController;
	}
	
	controller->setup();
}

void ArdunityAppClass::detachController(ArdunityController* controller)
{
	ArdunityController* c = firstController;
	ArdunityController* c1 = 0;

	while(c != 0)
	{
		if(c == controller)
		{
			if(c1 == 0)
				firstController = controller->nextController;
			else
				c1->nextController = controller->nextController;
			break;
		}
		
		c1 = c;
		c = c->nextController;
	}
}

void ArdunityAppClass::attachCallback(byte command, callbackFunction newFunction)
{
	switch(command)
	{
    	case CMD_START:
			startCallback = newFunction;
			break;

    	case CMD_EXIT:
			exitCallback = newFunction;
			break;
  	}
}

void ArdunityAppClass::detachCallback(byte command)
{
	switch(command)
	{
    	case CMD_START:
			startCallback = 0;
			break;

    	case CMD_EXIT:
			exitCallback = 0;
			break;
  	}
}

boolean ArdunityAppClass::push(byte* value, int size)
{
	if((MAX_ARGUMENT_BYTES - numArgument) < size)
		return false;
		
	for(int i=0; i<size; i++)
		storedArgument[numArgument++] = value[i];
	
	return true;
}

boolean ArdunityAppClass::push(UINT8 value)
{
	return push((byte*)&value, 1);
}

boolean ArdunityAppClass::push(INT8 value)
{
	return push((byte*)&value, 1);
}

boolean ArdunityAppClass::push(UINT16 value)
{
	return push((byte*)&value, 2);
}

boolean ArdunityAppClass::push(INT16 value)
{
	return push((byte*)&value, 2);
}

boolean ArdunityAppClass::push(UINT32 value)
{
	return push((byte*)&value, 4);
}

boolean ArdunityAppClass::push(INT32 value)
{
	return push((byte*)&value, 4);
}

boolean ArdunityAppClass::push(FLOAT32 value)
{
	return push((byte*)&value, 4);
}

boolean ArdunityAppClass::push(STRING value)
{
	byte size = 0;
	while(size < 255)
	{
		if(value[size] == '\0')
			break;
		size++;
	}
	
	if((MAX_ARGUMENT_BYTES - numArgument) < (size + 1))
		return false;
	
	storedArgument[numArgument++] = size;	
	for(int i=0; i<(int)size; i++)
		storedArgument[numArgument++] = value[i];
	
	return true;
}

boolean ArdunityAppClass::pop(byte* value, int size)
{
	if((numData - currentNumData) < size)
		return false;
	
	for(int i=0; i<size; i++)
		value[i] = storedData[currentNumData++];
}

boolean ArdunityAppClass::pop(UINT8* value)
{
	return pop((byte*)value, 1);
}

boolean ArdunityAppClass::pop(INT8* value)
{
	return pop((byte*)value, 1);
}

boolean ArdunityAppClass::pop(UINT16* value)
{
	return pop((byte*)value, 2);
}

boolean ArdunityAppClass::pop(INT16* value)
{
	return pop((byte*)value, 2);
}

boolean ArdunityAppClass::pop(UINT32* value)
{
	return pop((byte*)value, 4);
}

boolean ArdunityAppClass::pop(INT32* value)
{
	return pop((byte*)value, 4);
}

boolean ArdunityAppClass::pop(FLOAT32* value)
{
	return pop((byte*)value, 4);
}

boolean ArdunityAppClass::pop(STRING value, int maxSize)
{
	if((numData - currentNumData) < 1)
		return false;
	
	byte size = storedData[currentNumData++];
	
	if((numData - currentNumData) < size)
		return false;
		
	for(int i=0; i<(int)size; i++)
	{
		if(i < maxSize)
			value[i] = (char)storedData[currentNumData];

		currentNumData++;
	}
	
	if(size > maxSize)
		size = maxSize - 1;
	
	value[size] = '\0';
	return true;
}


//******************************************************************************
//* Private Methods
//******************************************************************************

// resets the system state upon a SYSTEM_RESET message from the host software
void ArdunityAppClass::Reset(void)
{
	if(processUpdate > 0)
    {
		commSocket->write(CMD_READY);
        commSocket->flush();
    }
	
	processUpdate = 0;
	numData = 0;
	currentNumData = 0;
	numArgument = 0;
}


ArdunityAppClass ArdunityApp;


PRO
USA
#28  
/*
  Ardunity.h - Ardunity Arduino library
  Copyright (C) 2015 ojh6t3k.  All rights reserved.
*/

#ifndef Ardunity_h
#define Ardunity_h

#include "Arduino.h"
#include "ArdunityController.h"

// Do not edit below contents
#define MAX_ARGUMENT_BYTES    116
#define CMD_START         0x80 // start
#define CMD_EXIT	      0x81 // exit
#define CMD_UPDATE        0x82 // update
#define CMD_EXECUTE       0x83 // execute
#define CMD_READY         0x84 // ready
#define CMD_PING	      0x85 // ping
#define CMD_RESET	      0x86 // reset
#define CMD_UNKNOWN	      0x87 // unknown

extern "C" {
  typedef void (*callbackFunction)(void);
}


class ArdunityAppClass
{
public:
	ArdunityAppClass();

	// for application
	void begin();
	void begin(long speed);
    void begin(Stream *s);
	void begin(Stream *s, Stream *s1);
    void resolution(int pwm, int adc);
    void timeout(unsigned long millisec);
    void process(void);
	void process(Stream *s);
    void attachController(ArdunityController* controller);
	void detachController(ArdunityController* controller);
	void attachCallback(byte command, callbackFunction newFunction);
	void detachCallback(byte command);

    // for module
    int maxPWM;
    int maxADC;
    
	void select(byte id);
	void flush();
	boolean push(UINT8 value);
	boolean push(INT8 value);
	boolean push(UINT16 value);
	boolean push(INT16 value);
	boolean push(UINT32 value);
	boolean push(INT32 value);
	boolean push(FLOAT32 value);
	boolean push(STRING value);
	boolean pop(UINT8* value);
	boolean pop(INT8* value);
	boolean pop(UINT16* value);
	boolean pop(INT16* value);
	boolean pop(UINT32* value);
	boolean pop(INT32* value);
	boolean pop(FLOAT32* value);
	boolean pop(STRING value, int maxSize);

private:
    Stream* commSocket;
    Stream* bypassSocket;
	ArdunityController* firstController;

	callbackFunction startCallback;
	callbackFunction exitCallback;

    boolean connected;
    unsigned long preTime;
    unsigned long timeoutMillis;
	boolean readyReceived;
    byte bypassProcessUpdate;
	byte processUpdate;
	byte ID;
	byte numData;
	byte currentNumData;
    byte storedData[MAX_ARGUMENT_BYTES + (MAX_ARGUMENT_BYTES / 8) + 1];
	byte numArgument;
	byte storedArgument[MAX_ARGUMENT_BYTES];
	
    void Reset(void);
	boolean push(byte* value, int size);
	boolean pop(byte* value, int size);
};

extern ArdunityAppClass ArdunityApp;

#endif

PRO
USA
#29  
/*
  ArdunityController.cpp - Ardunity Arduino library
  Copyright (C) 2015 ojh6t3k.  All rights reserved.
*/

//******************************************************************************
//* Includes
//******************************************************************************
#include "ArdunityController.h"
#include "Ardunity.h"


//******************************************************************************
//* Constructors
//******************************************************************************

ArdunityController::ArdunityController(int id)
{
	_id = (UINT8)id;
    started = false;
	updated = false;
	dirty = false;
    _enableUpdate = 1;	
	nextController = 0;
}

//******************************************************************************
//* Public Methods
//******************************************************************************
void ArdunityController::setup()
{
	OnSetup();
}

void ArdunityController::start()
{
    started = true;
	updated = false;
	dirty = true;
	OnStart();
}

void ArdunityController::stop()
{
    started = false;
	OnStop();
}

void ArdunityController::process()
{
	OnProcess();
}

boolean ArdunityController::update(byte id)
{
	if(_id == (UINT8)id)
	{
		OnUpdate();
		ArdunityApp.pop(&_enableUpdate);
		return true;
	}

	return false;
}

void ArdunityController::execute()
{
	if(updated)
	{
		OnExecute();		
		updated = false;
	}
}

void ArdunityController::flush()
{
    started = true;
	if(canFlush && (_enableUpdate == 1) && dirty)
	{
		ArdunityApp.select(_id);
		OnFlush();
		dirty = false;
		ArdunityApp.flush();
	}
}

PRO
USA
#30  
/*
  ArdunityController.h - Ardunity Arduino library
  Copyright (C) 2015 ojh6t3k.  All rights reserved.
*/

#ifndef ArdunityController_h
#define ArdunityController_h

#include "Arduino.h"

extern "C" {
typedef unsigned char UINT8;
typedef char INT8;
typedef unsigned short UINT16;
typedef short INT16;
typedef unsigned long UINT32;
typedef long INT32;
typedef float FLOAT32;
typedef char* STRING;
}


class ArdunityController
{
public:
	ArdunityController* nextController;

	ArdunityController(int id);

	void setup();
	void start();
	void stop();
	void process();
	boolean update(byte id);
	void execute();
	void flush();

protected:
    boolean canFlush;
    boolean started;
	boolean updated;
	boolean dirty;
	
	virtual void OnSetup() {}
	virtual void OnStart() {}
	virtual void OnStop() {}
	virtual void OnProcess() {}
	virtual void OnUpdate() {}
	virtual void OnExecute() {}
	virtual void OnFlush() {}

private:
	UINT8 _id;
	UINT8 _enableUpdate;
};

#endif

PRO
USA
#31  
/*
  GenericServo.cpp - Ardunity Arduino library
  Copyright (C) 2015 ojh6t3k.  All rights reserved.
*/

//******************************************************************************
//* Includes
//******************************************************************************
#include "Ardunity.h"
#include "GenericServo.h"


//******************************************************************************
//* Constructors
//******************************************************************************

GenericServo::GenericServo(int id, int pin, boolean smooth) : ArdunityController(id)
{
	_pin = pin;
	_smooth = smooth;
	_first = false;
    canFlush = false;
}

//******************************************************************************
//* Override Methods
//******************************************************************************
void GenericServo::OnSetup()
{
}

void GenericServo::OnStart()
{
	_servo.attach(_pin);
	_first = true;
}

void GenericServo::OnStop()
{
	_servo.detach();
}

void GenericServo::OnProcess()
{
	if(started && _smooth)
	{
		if(_curAngle != _endAngle)
		{
			float t = (float)(_endTime - millis()) / (float)(_endTime - _startTime);
			if(t <= 0)
				_curAngle = _endAngle;
			else
			{
				float a = (float)(_endAngle - _startAngle) * (1 - t);
				_curAngle = _startAngle + (int)a;
			}

			_servo.write(_curAngle);
		}
	}
}

void GenericServo::OnUpdate()
{
	UINT8 newAngle;
	ArdunityApp.pop(&newAngle);
	if(_angle != newAngle)
	{
		_angle = newAngle;
		updated = true;
	}
}

void GenericServo::OnExecute()
{
	if(_smooth)
	{
		if(_first)
		{
			_first = false;
			_curAngle = (int)_angle;
			_startAngle = _curAngle;
			_endAngle = _startAngle;
			_servo.write(_curAngle);
			_endTime = millis();
		}
		else
		{
			_startAngle = _curAngle;
			_endAngle = (int)_angle;
			_startTime = millis();
			_endTime = (_startTime - _endTime) + _startTime;
			if(_endTime <= _startTime)
			{
				// Timer overflow
				_curAngle = _endAngle;
				_startAngle = _endAngle;
				_servo.write(_curAngle);
				_endTime = _startTime;
			}
		}
	}
	else
	{
		_servo.write(_angle);
	}
}

void GenericServo::OnFlush()
{
}

//******************************************************************************
//* Private Methods
//******************************************************************************

PRO
USA
#32  
/*
  GenericServo.h - Ardunity Arduino library
  Copyright (C) 2015 ojh6t3k.  All rights reserved.
*/

#ifndef GenericServo_h
#define GenericServo_h

#include <Servo.h>
#include "ArdunityController.h"


class GenericServo : public ArdunityController
{
public:
	GenericServo(int id, int pin, boolean smooth);	

protected:
	void OnSetup();
	void OnStart();
	void OnStop();
	void OnProcess();
	void OnUpdate();
	void OnExecute();
	void OnFlush();

private:
    int _pin;
	boolean _smooth;
	boolean _first;
	int _startAngle;
	int _endAngle;
	int _curAngle;
	unsigned long _endTime;
	unsigned long _startTime;

	Servo _servo;
	UINT8 _angle;
};

#endif