User Tools

Translations of this page:

Site Tools


en:arduino_module_base_lesson

Getting Started

Messaging Basics

Only the orbiter control computer can initiate communications over the construction set bus. It can query various devices on the bus, including Arduino, in points of time specified by the user. It can also receive responses but only for a limited time that can be defined by the user using the function shown below. Therefore every time we want to initiate transfers or receive commands with Arduino there must be an explicit command to perform such an operation in the orbiter program.

Orbiter-Side Messaging

The following function invokes commands for interacting with Arduino:

int arduino_send(const uint16_t num, const uint16_t msg_id, char *args, char *answer, char *timeout)
  • The first argument is the Arduino index number (defaults to 0)
  • The second argument is the message ID (as necessary on the Arduino side depending on the program being executed)
  • The third argument is the data being transferred (NULL if none)
  • The fourth argument is the buffer to receive data (NULL if there is nothing to be received)
  • The fifth argument is the time to wait for a response from Arduino (in milliseconds). This value must be chosen by the user depending on the particular objective.

Arduino-Side Messaging

The Arduino side uses a special library orbicraftBus.arduinoLib.zip providing various methods for working with the bus of the construction set.

Description of methods:

Message Receipt Function
When a new message arrives it is written into the msg variable. The function returns message length in bytes (including identifiers), returning 0 when there is no message. -1 will be returned if there was a decoding error.

int16_t takeMessage(Message &msg)

The Message structure contains the following fields:

  • from: sender ID
  • to: recipient ID
  • id: message ID
  • data: a string of arguments

Message Sending Function
Returns the length of the message sent in bytes.

int16_t sendMessage(const uint16_t address, const uint16_t id, const String data)
  • address: recipient address
  • id: message ID
  • data: a string of arguments

Received Data Buffering Function
This method must be called from the serialEvent2() function – see sample code.

void serialEventProcess(void)

Device ID Setting Function
This function is necessary if there are multiple Arduino controllers on the bus.

void setArduinoNumber(const uint8_t newNumber)

newNumber is the new device number.

Function Returning the Device Number

uint8_t getArduinoNumber(void) 
Understanding the details of interoperation between the Orbicraft Construction Set and Arduino requires you to learn the COBS data transfer protocol along with some basics of object-oriented programming as you will encounter related terminology in code examples. We highly recommend you do that in order to grasp the principles behind the operation of the construction set data bus and its interoperation with the payload. A certain basic level of proficiency with the C/C++ programming language will also be necessary for writing code.

Transferring Commands to Arduino

If you have not done it yet, take some time to read the Getting Started section where the necessary preparations are explained.

In line with what has become a tradition in Arduino world, our first example will be a program that blinks the built-in LED. This LED is noted as DIR_LED on the shield. It should be noted that a built-in LED connected to pin 13 will also light up on the Arduino board.

Our approach to the use of arduino_send() will be as follows. By merely sending a message ID from the orbiter computer we will invoke an already existing function on the Arduino side implemented in the traditional Arduino way.

Orbiter-Side Code

Here our task is to send a message with an ID that will be used to invoke a function in Arduino.

See Getting Started for a refresher on how to design programs for the orbiter computer correctly.
ArduinoTestLed_1_Orbi.c
#include "libschsat.h"
 
void control(void)
{
 
	/* 
	* Transfer a command for executing command ID 1 to Arduino using the arduino_send built-in function
	* The first argument is the Arduino ID (defaults to 0)
        * The second argument is message ID (1 in our case)
        * The third argument is the data being transferred (NULL as we don’t have any data to send)
        * The fourth argument is the buffer to receive data (NULL as we don’t expect a response)
        * The fifth argument is the time to wait for a response from Arduino (100 ms in this case but it matters little in this case as we aren’t waiting for any response)
	*/
 
	arduino_send(0, 1, NULL, NULL, 100);
 
}

Arduino Code

Our task is to turn on the built-in LED for 3 seconds by sending a command from the orbiter computer and then turn it off. In order to accomplish that we must receive a packet containing an ID from the orbiter computer and execute the respective command by calling the LED control function.

To enable interaction between Arduino and orbiter computer, be sure to install an interoperability library in Arduino IDE first. The library can be found in the Required Software section.
ArduinoTestLed_1_Ard.ino
#include <OrbicraftBus.h> // Import the Orbicraft Construction Set control library
 
/*
  * Declare the msg variable as the Message data type
  * Message comprises a structure that contains IDs and transferred message content
*/
Message msg;
 
/*
  * Declare the bus variable as the OrbicraftBus data type 
  * OrbicraftBus is a class describing interaction between Arduino and Orbicraft construction set bus
*/
OrbicraftBus bus;
 
// Declare the msgSize variable to hold the size of the received message
uint16_t msgSize = 0;
 
void setup() {
  Serial1.begin(9600); // Define data transfer rate over Serial1 (Check Serial2.begin(9600))
}
 
void loop() {
  msgSize = bus.takeMessage(msg); // Try to read the message using the takeMessage method
  if (msgSize > 0){ //If there is a message…
    switch (msg.id){//Process in a particular manner depending on message ID
 
      // Consider the case with ID 1
        case 0x01:
          turnOnLed(); // Call the function for turning the LED on and off
          break;
    }         
  }
}
 
void turnOnLed(void){
  digitalWrite(LED_BUILTIN, HIGH); //Turn on the built-in LED
  delay(3000); //Wait 3 seconds
  digitalWrite (LED_BUILTIN, LOW); //Turn off the built-in LED
}
 
/*
 * The following block of code must always be appended to the program.
 * The function is called automatically and is necessary for message processing.
*/ 
void serialEvent2() {
  bus.serialEventProcess();
}

Retrieving Data from Arduino

Data from Arduino is received by the OCC using the same function on the OCC side:

int arduino_send(const uint16_t num, const uint16_t msg_id, char *args, char *answer)

It works in the same manner as when transferring commands from OCC to Arduino. The only difference is that arduino_send takes other arguments and the respective data to be sent will have to be generated on the Arduino side. For our example we will receive the data from the photoresistive cell (the illuminance sensor) connected to the pin A0 on Arduino. Commented code examples follow.

Before you connect the photoresistive cell to Arduino take some time to see how to do it properly. The photoresistive cell can be used as a separate component in combination with requisite peripherals or in the form of off-the-shelf module shipped with all necessary accessories.

Orbiter-Side Code

ArduinoTestLightSensor_1_Orbi.c
#include "libschsat.h"
 
	void control(void)
	{
		char answer[255]; // Create an array to hold the response
		int32_t count = 5; // Set the counter for 5 steps
/* 
	* Transfer a command for receiving the response with ID 2 to Arduino using the arduino_send built-in function
	* The first argument is the Arduino ID (defaults to 0)
        * The second argument is message ID (2 in our case)
        * The third argument is the data being transferred (NULL as we don’t have any data to send)
        * The fourth argument is the buffer to receive data (in our case it is the array named answer for incoming data)
	* The fifth argument is the time, in milliseconds, to wait for a response from Arduino (100 ms in our case).
*/
		while (count > 0){
			int status = arduino_send(0, 2, NULL, answer, 100);
			if (status == 0){
				printf("Answer: %s\r\n", answer);
			}
			else{
				printf("Error\r\n");
			}
			mSleep(500);
			count--;
		}
 
	}

Arduino Code

ArduinoLightSensor_1_Ard.ino
#include <OrbicraftBus.h>
 
/*
  * Declare the msg variable as the Message data type
  * Message comprises a structure that that describes the identifiers of the message being transferred
*/
Message msg;
 
/*
  * Declare the bus variable as the OrbicraftBus data type 
  * OrbicraftBus is a class describing interaction between Arduino and Orbicraft construction set bus
*/
OrbicraftBus bus;
 
// Declare the msgSize variable to hold the message being transferred
int16_t msgSize = 0;
// Declare the pin number to sense readings
int data_pin = A0; // These pin will be used for readouts from the sensor
 
void setup() {
  Serial1.begin(9600); // Define data transfer rate over Serial1 (Check Serial2.begin(9600))
}
 
void loop() {
 
  msgSize = bus.takeMessage(msg); // Try to read the message using the takeMessage method
 
  if (msgSize > 0){ //If there is a message…
    switch (msg.id){//Process in a particular manner depending on message ID
 
      // Consider the case with ID 2
        case 0x02:{
        String data = String(Sensor_data()); // Store readings obtained from Sensor_data() in the data variable
        bus.sendMessage(bus.obcAddress, 0, data); // пSend the contents of the data variable to the OCC
        break;
      }
    }
  }
}
 
uint16_t Sensor_data(void){
  uint16_t data = analogRead(data_pin); //Read illuminance values from the sensor
  return data;
}
 
/*
 * The following block of code must always be appended to the program.
 * The function is called automatically and is necessary for message processing.
*/ 
void serialEvent2() {
  bus.serialEventProcess();
}
en/arduino_module_base_lesson.txt · Last modified: 2020/01/20 16:26 by golikov