diff --git a/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/syntax/sensor/generic/Scd40Sensor.java b/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/syntax/sensor/generic/Scd40Sensor.java new file mode 100644 index 0000000000..dda2586357 --- /dev/null +++ b/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/syntax/sensor/generic/Scd40Sensor.java @@ -0,0 +1,18 @@ +package de.fhg.iais.roberta.syntax.sensor.generic; + +import de.fhg.iais.roberta.syntax.sensor.ExternalSensor; +import de.fhg.iais.roberta.transformer.forClass.F2M; +import de.fhg.iais.roberta.transformer.forClass.NepoExpr; +import de.fhg.iais.roberta.util.ast.BlocklyProperties; +import de.fhg.iais.roberta.util.ast.ExternalSensorBean; + +@NepoExpr(name = "SCD40_SENSING", category = "SENSOR", blocklyNames = {"robSensors_scd40_getSample"}, + sampleValues = {@F2M(field = "SCD40_CO2", mode = "CO2"), @F2M(field = "SCD40_TEMPERATURE", mode = "TEMPERATURE"), @F2M(field = "SCD40_HUMIDITY", mode = "HUMIDITY")}) +public final class Scd40Sensor extends ExternalSensor { + + public Scd40Sensor(BlocklyProperties properties, ExternalSensorBean externalSensorBean) { + super(properties, externalSensorBean); + setReadOnly(); + } + +} diff --git a/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/ast/AstFactory.java b/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/ast/AstFactory.java index 97a238a241..c7030239af 100644 --- a/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/ast/AstFactory.java +++ b/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/ast/AstFactory.java @@ -53,7 +53,7 @@ public class AstFactory { * the list of all legal modes used in the blockly frontend */ private static final String[] allLegalModesArray = { - "ALTITUDE", "AMBIENTLIGHT", "ANALOG", "ANGLE", "BACKWARD", "BALL", "CALIBRATE", "CALIBRATION", "CLOSING", "CO2EQUIVALENT", "COLOUR", "COMPASS", + "ALTITUDE", "AMBIENTLIGHT", "ANALOG", "ANGLE", "BACKWARD", "BALL", "CALIBRATE", "CALIBRATION", "CLOSING", "CO2", "CO2EQUIVALENT", "COLOUR", "COMPASS", "DATE", "DEFAULT", "DEGREE", "DIGITAL", "DISTANCE", "DOWN", "EDISON_CODE", "FACE_DOWN", "FACE_UP", "FOREWARD", "FREEFALL", "G3", "G6", "G8", "HUMIDITY", "IAQ", "IDALL", "IDONE", "LATITUDE", "LEFT", "LIGHT", "LIGHT_VALUE", "LINE", "LONGITUDE", "MODULATED", "MOTION", "NAMEALL", "NAMEONE", "NONE", "OBSTACLE", "OFF", "OPENING", "NUMBERLINES", "PM10", "PM25", "PRESENCE", "PRESSED", "PRESSURE", "PULSEHIGH", "PULSELOW", "RATE", @@ -247,4 +247,4 @@ private static void addToSampleValues(F2M[] fieldToModeArray, BlockDescriptor bl getSensorSampleMap.put(f2M.field(), blockDescriptor); } } -} \ No newline at end of file +} diff --git a/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/syntax/SC.java b/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/syntax/SC.java index 8be72e1a37..3659a0c451 100644 --- a/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/syntax/SC.java +++ b/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/util/syntax/SC.java @@ -21,6 +21,7 @@ public interface SC { String ULTRASONIC = "ULTRASONIC"; String SOUND = "SOUND"; String DISTANCE = "DISTANCE"; + String CO2 = "CO2"; String RESET = "RESET"; String ROTATION = "ROTATION"; String DEGREE = "DEGREE"; @@ -128,6 +129,7 @@ public interface SC { String MUSIC = "MUSIC"; String ENVIRONMENTAL = "ENVIRONMENTAL"; String COLOURTCS3472 = "COLOURTCS3472"; + String SCD40 = "SCD40"; String LED_BUILTIN = "LED_BUILTIN"; String GREEN = "GREEN"; String BLUE = "BLUE"; diff --git a/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/visitor/TransformerVisitor.java b/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/visitor/TransformerVisitor.java index 867e9ff440..d264498660 100644 --- a/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/visitor/TransformerVisitor.java +++ b/OpenRobertaRobot/src/main/java/de/fhg/iais/roberta/visitor/TransformerVisitor.java @@ -139,6 +139,7 @@ import de.fhg.iais.roberta.syntax.sensor.generic.PinTouchSensor; import de.fhg.iais.roberta.syntax.sensor.generic.PulseSensor; import de.fhg.iais.roberta.syntax.sensor.generic.RfidSensor; +import de.fhg.iais.roberta.syntax.sensor.generic.Scd40Sensor; import de.fhg.iais.roberta.syntax.sensor.generic.SoundSensor; import de.fhg.iais.roberta.syntax.sensor.generic.TemperatureSensor; import de.fhg.iais.roberta.syntax.sensor.generic.TimerReset; @@ -767,6 +768,10 @@ public Phrase visitHumiditySensor(HumiditySensor humiditySensor) { return new HumiditySensor(humiditySensor.getProperty(), new ExternalSensorBean(humiditySensor.getUserDefinedPort(), humiditySensor.getMode(), humiditySensor.getSlot(), humiditySensor.getMutation())); } + public Phrase visitScd40Sensor(Scd40Sensor scd40Sensor) { + return new Scd40Sensor(scd40Sensor.getProperty(), new ExternalSensorBean(scd40Sensor.getUserDefinedPort(), scd40Sensor.getMode(), scd40Sensor.getSlot(), scd40Sensor.getMutation())); + } + public Phrase visitMotionSensor(MotionSensor motionSensor) { return new MotionSensor(motionSensor.getProperty(), new ExternalSensorBean(motionSensor.getUserDefinedPort(), motionSensor.getMode(), motionSensor.getSlot(), motionSensor.getMutation())); } diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2016/sensor_scd40.ast b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2016/sensor_scd40.ast new file mode 100644 index 0000000000..2c345acb7f --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2016/sensor_scd40.ast @@ -0,0 +1,3 @@ +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, CO2, - EMPTY_SLOT -]]] +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, TEMPERATURE, - EMPTY_SLOT -]]] +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, HUMIDITY, - EMPTY_SLOT -]]] diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2017/sensor_scd40.ast b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2017/sensor_scd40.ast new file mode 100644 index 0000000000..2c345acb7f --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2017/sensor_scd40.ast @@ -0,0 +1,3 @@ +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, CO2, - EMPTY_SLOT -]]] +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, TEMPERATURE, - EMPTY_SLOT -]]] +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, HUMIDITY, - EMPTY_SLOT -]]] diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2017NoBlue/sensor_scd40.ast b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2017NoBlue/sensor_scd40.ast new file mode 100644 index 0000000000..2c345acb7f --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliope2017NoBlue/sensor_scd40.ast @@ -0,0 +1,3 @@ +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, CO2, - EMPTY_SLOT -]]] +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, TEMPERATURE, - EMPTY_SLOT -]]] +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, HUMIDITY, - EMPTY_SLOT -]]] diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliopev3/sensor_scd40.ast b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliopev3/sensor_scd40.ast new file mode 100644 index 0000000000..2c345acb7f --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/astGenerated/calliopev3/sensor_scd40.ast @@ -0,0 +1,3 @@ +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, CO2, - EMPTY_SLOT -]]] +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, TEMPERATURE, - EMPTY_SLOT -]]] +SerialWriteAction[value: SensorExpr [Scd40Sensor [SCD, HUMIDITY, - EMPTY_SLOT -]]] diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2016/sensor_scd40.txt b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2016/sensor_scd40.txt new file mode 100644 index 0000000000..ad91fde02c --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2016/sensor_scd40.txt @@ -0,0 +1,6 @@ +Sensors: +[UsedSensor [SCD, SCD40, CO2], UsedSensor [SCD, SCD40, TEMPERATURE], UsedSensor [SCD, SCD40, HUMIDITY]] +Actors: +[] +Methods: +[SCD40_GET_SAMPLE] \ No newline at end of file diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2017/sensor_scd40.txt b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2017/sensor_scd40.txt new file mode 100644 index 0000000000..ad91fde02c --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2017/sensor_scd40.txt @@ -0,0 +1,6 @@ +Sensors: +[UsedSensor [SCD, SCD40, CO2], UsedSensor [SCD, SCD40, TEMPERATURE], UsedSensor [SCD, SCD40, HUMIDITY]] +Actors: +[] +Methods: +[SCD40_GET_SAMPLE] \ No newline at end of file diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2017NoBlue/sensor_scd40.txt b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2017NoBlue/sensor_scd40.txt new file mode 100644 index 0000000000..ad91fde02c --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliope2017NoBlue/sensor_scd40.txt @@ -0,0 +1,6 @@ +Sensors: +[UsedSensor [SCD, SCD40, CO2], UsedSensor [SCD, SCD40, TEMPERATURE], UsedSensor [SCD, SCD40, HUMIDITY]] +Actors: +[] +Methods: +[SCD40_GET_SAMPLE] \ No newline at end of file diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliopev3/sensor_scd40.txt b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliopev3/sensor_scd40.txt new file mode 100644 index 0000000000..ad91fde02c --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/collectorResults/calliopev3/sensor_scd40.txt @@ -0,0 +1,6 @@ +Sensors: +[UsedSensor [SCD, SCD40, CO2], UsedSensor [SCD, SCD40, TEMPERATURE], UsedSensor [SCD, SCD40, HUMIDITY]] +Actors: +[] +Methods: +[SCD40_GET_SAMPLE] \ No newline at end of file diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2016/sensor_scd40.cpp b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2016/sensor_scd40.cpp new file mode 100644 index 0000000000..ba75a8b5c4 --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2016/sensor_scd40.cpp @@ -0,0 +1,74 @@ +#define _GNU_SOURCE + +#include "MicroBit.h" +#include "NEPODefs.h" +#include +#include +#include +MicroBit _uBit; +MicroBitI2C _i2c(MICROBIT_PIN_P20, MICROBIT_PIN_P19); + + +double scd40_get_sample(int mode); + + +int main() +{ + _uBit.init(); + + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(0))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(0)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(1))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(1)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(2))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(2)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + release_fiber(); +} + +double scd40_get_sample(int mode) { + static bool started = false; + static double values[3] = { 0, 0, 0 }; + const int address = 0x62 << 1; + if ( !started ) { + char startCommand[2] = { 0x21, (char) 0xb1 }; + _i2c.write(address, startCommand, 2); + _uBit.sleep(5000); + started = true; + } + + char readCommand[2] = { (char) 0xec, 0x05 }; + char data[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + _i2c.write(address, readCommand, 2); + _uBit.sleep(1); + if ( _i2c.read(address, data, 9) == 0 ) { + bool crcValid = true; + for ( int word = 0; word < 3; word++ ) { + uint8_t crc = 0xff; + for ( int i = 0; i < 2; i++ ) { + crc ^= (uint8_t) data[word * 3 + i]; + for ( int bit = 0; bit < 8; bit++ ) { + if ( crc & 0x80 ) { + crc = (uint8_t) ((crc << 1) ^ 0x31); + } else { + crc = (uint8_t) (crc << 1); + } + } + } + if ( crc != (uint8_t) data[word * 3 + 2] ) { + crcValid = false; + } + } + if ( crcValid ) { + uint16_t co2 = ((uint8_t) data[0] << 8) | (uint8_t) data[1]; + uint16_t rawTemperature = ((uint8_t) data[3] << 8) | (uint8_t) data[4]; + uint16_t rawHumidity = ((uint8_t) data[6] << 8) | (uint8_t) data[7]; + values[0] = co2; + values[1] = -45.0 + 175.0 * rawTemperature / 65535.0; + values[2] = 100.0 * rawHumidity / 65535.0; + } + } + return values[mode]; +} diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2017/sensor_scd40.cpp b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2017/sensor_scd40.cpp new file mode 100644 index 0000000000..ba75a8b5c4 --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2017/sensor_scd40.cpp @@ -0,0 +1,74 @@ +#define _GNU_SOURCE + +#include "MicroBit.h" +#include "NEPODefs.h" +#include +#include +#include +MicroBit _uBit; +MicroBitI2C _i2c(MICROBIT_PIN_P20, MICROBIT_PIN_P19); + + +double scd40_get_sample(int mode); + + +int main() +{ + _uBit.init(); + + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(0))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(0)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(1))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(1)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(2))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(2)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + release_fiber(); +} + +double scd40_get_sample(int mode) { + static bool started = false; + static double values[3] = { 0, 0, 0 }; + const int address = 0x62 << 1; + if ( !started ) { + char startCommand[2] = { 0x21, (char) 0xb1 }; + _i2c.write(address, startCommand, 2); + _uBit.sleep(5000); + started = true; + } + + char readCommand[2] = { (char) 0xec, 0x05 }; + char data[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + _i2c.write(address, readCommand, 2); + _uBit.sleep(1); + if ( _i2c.read(address, data, 9) == 0 ) { + bool crcValid = true; + for ( int word = 0; word < 3; word++ ) { + uint8_t crc = 0xff; + for ( int i = 0; i < 2; i++ ) { + crc ^= (uint8_t) data[word * 3 + i]; + for ( int bit = 0; bit < 8; bit++ ) { + if ( crc & 0x80 ) { + crc = (uint8_t) ((crc << 1) ^ 0x31); + } else { + crc = (uint8_t) (crc << 1); + } + } + } + if ( crc != (uint8_t) data[word * 3 + 2] ) { + crcValid = false; + } + } + if ( crcValid ) { + uint16_t co2 = ((uint8_t) data[0] << 8) | (uint8_t) data[1]; + uint16_t rawTemperature = ((uint8_t) data[3] << 8) | (uint8_t) data[4]; + uint16_t rawHumidity = ((uint8_t) data[6] << 8) | (uint8_t) data[7]; + values[0] = co2; + values[1] = -45.0 + 175.0 * rawTemperature / 65535.0; + values[2] = 100.0 * rawHumidity / 65535.0; + } + } + return values[mode]; +} diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2017NoBlue/sensor_scd40.cpp b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2017NoBlue/sensor_scd40.cpp new file mode 100644 index 0000000000..ba75a8b5c4 --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliope2017NoBlue/sensor_scd40.cpp @@ -0,0 +1,74 @@ +#define _GNU_SOURCE + +#include "MicroBit.h" +#include "NEPODefs.h" +#include +#include +#include +MicroBit _uBit; +MicroBitI2C _i2c(MICROBIT_PIN_P20, MICROBIT_PIN_P19); + + +double scd40_get_sample(int mode); + + +int main() +{ + _uBit.init(); + + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(0))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(0)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(1))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(1)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + _uBit.serial.setTxBufferSize(ManagedString((scd40_get_sample(2))).length() + 2); + _uBit.serial.send(ManagedString(scd40_get_sample(2)) + "\r\n", MicroBitSerialMode::ASYNC); + _uBit.sleep(_ITERATION_SLEEP_TIMEOUT); + release_fiber(); +} + +double scd40_get_sample(int mode) { + static bool started = false; + static double values[3] = { 0, 0, 0 }; + const int address = 0x62 << 1; + if ( !started ) { + char startCommand[2] = { 0x21, (char) 0xb1 }; + _i2c.write(address, startCommand, 2); + _uBit.sleep(5000); + started = true; + } + + char readCommand[2] = { (char) 0xec, 0x05 }; + char data[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + _i2c.write(address, readCommand, 2); + _uBit.sleep(1); + if ( _i2c.read(address, data, 9) == 0 ) { + bool crcValid = true; + for ( int word = 0; word < 3; word++ ) { + uint8_t crc = 0xff; + for ( int i = 0; i < 2; i++ ) { + crc ^= (uint8_t) data[word * 3 + i]; + for ( int bit = 0; bit < 8; bit++ ) { + if ( crc & 0x80 ) { + crc = (uint8_t) ((crc << 1) ^ 0x31); + } else { + crc = (uint8_t) (crc << 1); + } + } + } + if ( crc != (uint8_t) data[word * 3 + 2] ) { + crcValid = false; + } + } + if ( crcValid ) { + uint16_t co2 = ((uint8_t) data[0] << 8) | (uint8_t) data[1]; + uint16_t rawTemperature = ((uint8_t) data[3] << 8) | (uint8_t) data[4]; + uint16_t rawHumidity = ((uint8_t) data[6] << 8) | (uint8_t) data[7]; + values[0] = co2; + values[1] = -45.0 + 175.0 * rawTemperature / 65535.0; + values[2] = 100.0 * rawHumidity / 65535.0; + } + } + return values[mode]; +} diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliopev3/sensor_scd40.py b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliopev3/sensor_scd40.py new file mode 100644 index 0000000000..0cb375f70e --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/_expected/robotSpecific/targetLanguage/calliopev3/sensor_scd40.py @@ -0,0 +1,75 @@ +import calliopemini +import random +import math + + +def scd40_get_sample(mode): + global _scd40_i2c_initialized, _scd40_started, _scd40_values + try: + _scd40_started + except NameError: + _scd40_i2c_initialized = False + _scd40_started = False + _scd40_values = (0, 0, 0) + + def scd40_crc(data): + crc = 0xff + for byte in data: + crc ^= byte + for _ in range(8): + if crc & 0x80: + crc = ((crc << 1) ^ 0x31) & 0xff + else: + crc = (crc << 1) & 0xff + return crc + + if not _scd40_i2c_initialized: + try: + if hasattr(calliopemini, "pin_A0_SCL") and hasattr(calliopemini, "pin_A0_SDA"): + calliopemini.i2c.init(freq=400000, scl=calliopemini.pin_A0_SCL, sda=calliopemini.pin_A0_SDA) + elif hasattr(calliopemini, "pin_C19") and hasattr(calliopemini, "pin_C20"): + calliopemini.i2c.init(freq=400000, scl=calliopemini.pin_C19, sda=calliopemini.pin_C20) + except Exception: + pass + _scd40_i2c_initialized = True + + try: + if not _scd40_started: + calliopemini.i2c.write(0x62, b'\x21\xb1') + calliopemini.sleep(5000) + _scd40_started = True + + calliopemini.i2c.write(0x62, b'\xec\x05') + calliopemini.sleep(1) + data = calliopemini.i2c.read(0x62, 9) + except Exception: + return _scd40_values[mode] + + if len(data) >= 9 and scd40_crc(data[0:2]) == data[2] and scd40_crc(data[3:5]) == data[5] and scd40_crc(data[6:8]) == data[8]: + co2 = (data[0] << 8) | data[1] + raw_temperature = (data[3] << 8) | data[4] + raw_humidity = (data[6] << 8) | data[7] + _scd40_values = (co2, -45 + 175 * raw_temperature / 65535, 100 * raw_humidity / 65535) + + return _scd40_values[mode] + +class BreakOutOfALoop(Exception): pass +class ContinueLoop(Exception): pass + +timer1 = calliopemini.running_time() + + +def run(): + global timer1 + print(scd40_get_sample(0)) + print(scd40_get_sample(1)) + print(scd40_get_sample(2)) + +def main(): + try: + run() + except Exception as e: + raise + +if __name__ == "__main__": + main() diff --git a/OpenRobertaServer/src/test/resources/crossCompilerTests/robotSpecific/calliope/sensor_scd40.xml b/OpenRobertaServer/src/test/resources/crossCompilerTests/robotSpecific/calliope/sensor_scd40.xml new file mode 100644 index 0000000000..6ab9a259c8 --- /dev/null +++ b/OpenRobertaServer/src/test/resources/crossCompilerTests/robotSpecific/calliope/sensor_scd40.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + CO2 + SCD + + + + + + + + + TEMPERATURE + SCD + + + + + + + + + HUMIDITY + SCD + + + + + + + + + + + + B + B + + + + + _S + + + + + SCD + A0 + + + + + _L + + + + + _G + + + + + _C + + + + + undefined + + + + + A + A + + + + + _A + + + + + _T + + + + + _R + + + + + _B + + + + + diff --git a/OpenRobertaServer/staticResources/blockly/blockly_compressed.js b/OpenRobertaServer/staticResources/blockly/blockly_compressed.js index 0fb38e23b4..47994c0255 100644 --- a/OpenRobertaServer/staticResources/blockly/blockly_compressed.js +++ b/OpenRobertaServer/staticResources/blockly/blockly_compressed.js @@ -1798,7 +1798,7 @@ Blockly.Msg.MESSAGE_FIRMWARE_ERROR="The firmware of your robot is newer than tha Blockly.Msg.MESSAGE_NOT_AVAILABLE="Not available.";Blockly.Msg.MESSAGE_PROGRAM_DELETED="Program \u00bb$\u00ab was deleted";Blockly.Msg.MESSAGE_RESTART_ROBOT="Please reconnect the robot to the Open Roberta Lab.";Blockly.Msg.MESSAGE_ROBOT_CONNECTED="Your robot \u00bb$\u00ab is connected";Blockly.Msg.MESSAGE_ROBOT_DISCONNECTED="An active robot was disconnected";Blockly.Msg.MESSAGE_USER_DELETED="User deleted";Blockly.Msg.MESSAGE_USER_GROUP_DELETED="User \u00bb$\u00ab was deleted"; Blockly.Msg.MESSAGE_USER_LOGIN="Hello \u00bb$\u00ab";Blockly.Msg.MESSAGE_USER_LOGOUT="You are logged out";Blockly.Msg.MICROBITBRICK_TOOLTIP="Represents micro:bit, a pocket-sized codeable computer. There are also inbuilt actors and sensors available, e.g. buttons, display ...";Blockly.Msg.MICROPHONE_GETSAMPLE_TOOLTIP="Gets the current reading from the microphone in % (mapped to 0 - 100). If the value is always low, the value has to be multiplied by 10, because the amplification is missing on the hardware."; Blockly.Msg.MIN_ANGLE="Minimum angle";Blockly.Msg.MIN_PULSE_WIDTH="Minimum pulse width";Blockly.Msg.MODE="mode";Blockly.Msg.MODE_ACCELERATION="acceleration";Blockly.Msg.MODE_ACCURACY="accuracy";Blockly.Msg.MODE_ALTITUDE="altitude";Blockly.Msg.MODE_AMBIENTLIGHT="ambient light";Blockly.Msg.MODE_ANALOG="analog value";Blockly.Msg.MODE_ANGLE="angle";Blockly.Msg.MODE_BALL="ball information";Blockly.Msg.MODE_CALIBRATION="Calibration Value";Blockly.Msg.MODE_CALIBRATIONNEED="calibration needed"; -Blockly.Msg.MODE_CAPACITIVE="capacitive";Blockly.Msg.MODE_CLAP="clap";Blockly.Msg.MODE_CLOSE="close";Blockly.Msg.MODE_CLOSING="dark";Blockly.Msg.MODE_CO2EQUIVALENT="CO2 Equivalent";Blockly.Msg.MODE_COLOR="color";Blockly.Msg.MODE_COLOUR="colour";Blockly.Msg.MODE_COMPASS="compass";Blockly.Msg.MODE_CURRENT="current";Blockly.Msg.MODE_DATE="date";Blockly.Msg.MODE_DEGREE="degree";Blockly.Msg.MODE_DIGITAL="digital value";Blockly.Msg.MODE_DISTANCE="distance";Blockly.Msg.MODE_FORCE="force"; +Blockly.Msg.MODE_CAPACITIVE="capacitive";Blockly.Msg.MODE_CLAP="clap";Blockly.Msg.MODE_CLOSE="close";Blockly.Msg.MODE_CLOSING="dark";Blockly.Msg.MODE_CO2="CO2";Blockly.Msg.MODE_CO2EQUIVALENT="CO2 Equivalent";Blockly.Msg.MODE_COLOR="color";Blockly.Msg.MODE_COLOUR="colour";Blockly.Msg.MODE_COMPASS="compass";Blockly.Msg.MODE_CURRENT="current";Blockly.Msg.MODE_DATE="date";Blockly.Msg.MODE_DEGREE="degree";Blockly.Msg.MODE_DIGITAL="digital value";Blockly.Msg.MODE_DISTANCE="distance";Blockly.Msg.MODE_FORCE="force"; Blockly.Msg.MODE_GESTURE="gesture";Blockly.Msg.MODE_GYRO="gyroscope";Blockly.Msg.MODE_HUMIDITY="humidity";Blockly.Msg.MODE_IAQ="Indoor Air Quality (IAQ)";Blockly.Msg.MODE_IDALL="IDs (list)";Blockly.Msg.MODE_IDONE="ID";Blockly.Msg.MODE_INFO="information";Blockly.Msg.MODE_LATITUDE="latitude";Blockly.Msg.MODE_LIGHT="light";Blockly.Msg.MODE_LINE="line";Blockly.Msg.MODE_LONGITUDE="longitude";Blockly.Msg.MODE_MAGNETICFIELD="mag field";Blockly.Msg.MODE_MAGNETICFLUX="magnetic flux"; Blockly.Msg.MODE_MODULATED="modulated";Blockly.Msg.MODE_MOISTURE="moisture";Blockly.Msg.MODE_MOTION="motion";Blockly.Msg.MODE_NAMEALL="names (list)";Blockly.Msg.MODE_NAMEONE="name";Blockly.Msg.MODE_NOT_SUPPORTED="The selected mode of this block is not supported by this system!";Blockly.Msg.MODE_NUMBERLINES="number of lines";Blockly.Msg.MODE_OBSTACLE="obstacle";Blockly.Msg.MODE_OPEN="open";Blockly.Msg.MODE_OPENING="light";Blockly.Msg.MODE_ORIENTATION="orientation";Blockly.Msg.MODE_PM10="PM10"; Blockly.Msg.MODE_PM25="PM2.5";Blockly.Msg.MODE_PRESENCE="presence";Blockly.Msg.MODE_PRESSED="pressed";Blockly.Msg.MODE_PRESSURE="pressure";Blockly.Msg.MODE_PROXIMITY="proximity";Blockly.Msg.MODE_PULSEHIGH="pulse time HIGH";Blockly.Msg.MODE_PULSELOW="pulse time LOW";Blockly.Msg.MODE_RATE="rate";Blockly.Msg.MODE_RCCODE="R/C code";Blockly.Msg.MODE_REFLEXION="reflected light";Blockly.Msg.MODE_RESISTANCE="resistance ";Blockly.Msg.MODE_RESISTIVE="resistive";Blockly.Msg.MODE_RGB="RGB"; @@ -1901,7 +1901,7 @@ Blockly.Msg.SENSOR_ACCELEROMETER_X_GETSAMPLE_TOOLTIP_SENSEBOX="Returns the accel Blockly.Msg.SENSOR_ACCELEROMETER_Z_GETSAMPLE_TOOLTIP_ARDUINO="Returns the acceleration value on the Z axis in g. Can be in range from -4 g to 4 g.";Blockly.Msg.SENSOR_ACCELEROMETER_Z_GETSAMPLE_TOOLTIP_SENSEBOX="Returns the acceleration value on the Z axis in g. Can be in range from -2 g to 2 g.";Blockly.Msg.SENSOR_AMBIENTLIGHT="ambientlight sensor";Blockly.Msg.SENSOR_ANALOGOUT="sensor analog";Blockly.Msg.SENSOR_ANY="anyplace";Blockly.Msg.SENSOR_APDS9960="APDS9960";Blockly.Msg.SENSOR_ARM_TOOLTIP="Returns true, if the selected part of the arm is touched, otherwise false."; Blockly.Msg.SENSOR_BALLDETECTOR="ball detector";Blockly.Msg.SENSOR_BALLDETECTOR_BALL_GETSAMPLE_TOOLTIP="Returns a list [x, y, diameter] representing information about a ball matching the color set in the configuration. If no ball is found, returns a list of [-1, -1, -1].";Blockly.Msg.SENSOR_BATTERY="battery charge";Blockly.Msg.SENSOR_BOTTOM="bottom";Blockly.Msg.SENSOR_CALIBRATE="calibrate";Blockly.Msg.SENSOR_CAMERA="camera";Blockly.Msg.SENSOR_CAMERA_GETSAMPLE_TOOLTIP="Returns the x-position in pixels of the left most point of a line or -1 if no line was found."; Blockly.Msg.SENSOR_CAMERA_THRESHOLD_TOOLTIP="Sets the threshold for color filtering for the marker and color recognition.";Blockly.Msg.SENSOR_CODE="code pad";Blockly.Msg.SENSOR_COLORDETECTOR="colour detector";Blockly.Msg.SENSOR_COLORDETECTOR_COLOUR_GETSAMPLE_TOOLTIP="Returns the average color of the specified camera area (configuration).";Blockly.Msg.SENSOR_COLOUR="colour sensor";Blockly.Msg.SENSOR_COLOURBLOB_TOOLTIP="Returns information as a list [x, y, size] about the biggest found area of a color in a specific HSV-range in pixels."; -Blockly.Msg.SENSOR_COLOURTCS3472="colour sensor TCS3472";Blockly.Msg.SENSOR_COLOUR_EDISON="line tracker";Blockly.Msg.SENSOR_COMPASS="compass sensor";Blockly.Msg.SENSOR_COMPASS_EV3="HT compass sensor";Blockly.Msg.SENSOR_COUNTER="counter";Blockly.Msg.SENSOR_DATA_READY="ready?";Blockly.Msg.SENSOR_DETECTFACE="face detector";Blockly.Msg.SENSOR_DETECTFACE_GETSAMPLE_TOOLTIP="Detect a face previously learned and saved.";Blockly.Msg.SENSOR_DETECTMARK="marker sensor"; +Blockly.Msg.SENSOR_COLOURTCS3472="colour sensor TCS3472";Blockly.Msg.SENSOR_SCD40="CO2 sensor SCD40";Blockly.Msg.SCD40_TOOLTIP="Represents an SCD40 CO2, temperature and humidity sensor.";Blockly.Msg.SENSOR_SCD40_CO2_GETSAMPLE_TOOLTIP="Gets the current CO2 concentration from the SCD40 sensor in ppm.";Blockly.Msg.SENSOR_SCD40_TEMPERATURE_GETSAMPLE_TOOLTIP="Gets the current temperature from the SCD40 sensor in degrees Celsius.";Blockly.Msg.SENSOR_SCD40_HUMIDITY_GETSAMPLE_TOOLTIP="Gets the current relative humidity from the SCD40 sensor in percent.";Blockly.Msg.SENSOR_COLOUR_EDISON="line tracker";Blockly.Msg.SENSOR_COMPASS="compass sensor";Blockly.Msg.SENSOR_COMPASS_EV3="HT compass sensor";Blockly.Msg.SENSOR_COUNTER="counter";Blockly.Msg.SENSOR_DATA_READY="ready?";Blockly.Msg.SENSOR_DETECTFACE="face detector";Blockly.Msg.SENSOR_DETECTFACE_GETSAMPLE_TOOLTIP="Detect a face previously learned and saved.";Blockly.Msg.SENSOR_DETECTMARK="marker sensor"; Blockly.Msg.SENSOR_DETECTMARK_GETSAMPLE_TOOLTIP="Returns one or an array of IDs (number) of the last detected NAO Mark(s). If no marks are detected, -1 or an array consisting of 1 element with value -1 is returned. For a list of NAO marks with corresponding numbers refer to the wiki.";Blockly.Msg.SENSOR_DETECTMARK_IDALL_GETSAMPLE_TOOLTIP_ROBOTINO="Returns a list IDs (number) of the currently detected marker(s). If no markers are detected, returns a list containing -1."; Blockly.Msg.SENSOR_DETECTMARK_NAO="NAO Mark sensor";Blockly.Msg.SENSOR_DIGITALOUT="sensor digital";Blockly.Msg.SENSOR_DROP="drop sensor";Blockly.Msg.SENSOR_DROP_GETSAMPLE_TOOLTIP="Gets the current reading from the drop sensor in percent.";Blockly.Msg.SENSOR_DROP_OFF="drop-off sensor";Blockly.Msg.SENSOR_ELECTRICCURRENT="current sensor";Blockly.Msg.SENSOR_ELECTRICCURRENT_GETSAMPLE_TOOLTIP="Get the electric current from the motorboard in the selected joint.";Blockly.Msg.SENSOR_ENCODER="encoder"; Blockly.Msg.SENSOR_ENVIRONMENTAL="environmental sensor";Blockly.Msg.SENSOR_ENVIRONMENTAL_CALIBRATION_TOOLTIP="Calibrates the environmental sensor. This takes several minutes.";Blockly.Msg.SENSOR_ENVIRONMENTAL_GETSAMPLE_TOOLTIP="Returns values from the environmental sensor.";Blockly.Msg.SENSOR_FLAME="flame sensor";Blockly.Msg.SENSOR_FSR="force-sensing resistor";Blockly.Msg.SENSOR_FSR_GETSAMPLE_TOOLTIP="Get the current reading from the force sensitive resistor under the feet of the robot."; @@ -2599,7 +2599,7 @@ confBlocks.light.joycar=confBlocks.light.microbitv2;confBlocks.light.mbot2=confB confBlocks.light.raspberrypi={title:"LIGHT",ports:[["output","OUTPUT"]],pins:Blockly.Blocks.robConfigDefinitions.pinsRaspberrypi,sensor:!0,standardPins:["18"],fixedPorts:[["VCC","3V3"],["GND","GND"]]};confBlocks.light.txt4={title:"LIGHT",ports:[["BRICK_PORT","PORT"]],pins:function(a){return Blockly.Blocks.robConfigDefinitions.txt4InputPorts},sensor:!0,standardPins:["I1"],fixedPorts:[["VCC","9V"]]};confBlocks.phototransistor={}; confBlocks.phototransistor.txt4={title:"PHOTOTRANSISTOR",ports:[["BRICK_PORT","PORT"]],pins:function(a){return Blockly.Blocks.robConfigDefinitions.txt4InputPorts},sensor:!0,standardPins:["I1"],fixedPorts:[["VCC","9V"]]};confBlocks.lightveml={};confBlocks.lightveml.sensebox={title:"LIGHTVEML",ports:[["I2C","I2C"]],pins:function(a){return[["I2C","I2C"]]},sensor:!0};confBlocks.accelerometer={};confBlocks.accelerometer.calliope={title:"ACCELEROMETER",ports:[["pin","PIN1"]],sensor:!0,inbuilt:!0}; confBlocks.accelerometer.microbit=confBlocks.accelerometer.calliope;confBlocks.accelerometer.microbitv2=confBlocks.accelerometer.calliope;confBlocks.accelerometer.joycar=confBlocks.accelerometer.microbitv2;confBlocks.accelerometer.mbot2=confBlocks.accelerometer.calliope;confBlocks.accelerometer.sensebox={title:"ACCELEROMETER",sensor:!0};confBlocks.accelerometer.arduino=confBlocks.accelerometer.sensebox;confBlocks.colourtcs3472={}; -confBlocks.colourtcs3472.calliope={title:"COLOURTCS3472",ports:[["pin","PIN1"]],dropdowns:[["GAIN",[["1x","1X"],["4x","4X"],["16x","16X"],["60x","60X"]]],["I_TIME",[["2.4ms","2_4MS"],["24ms","24MS"],["50ms","50MS"],["101ms","101MS"],["154ms","154MS"],["700ms","700MS"]]]],pins:function(a){return[["A0","A0"]]},sensor:!0};confBlocks.compass={};confBlocks.compass.calliope={title:"COMPASS",ports:[["pin","PIN1"]],sensor:!0,inbuilt:!0};confBlocks.compass.microbit=confBlocks.compass.calliope; +confBlocks.colourtcs3472.calliope={title:"COLOURTCS3472",ports:[["pin","PIN1"]],dropdowns:[["GAIN",[["1x","1X"],["4x","4X"],["16x","16X"],["60x","60X"]]],["I_TIME",[["2.4ms","2_4MS"],["24ms","24MS"],["50ms","50MS"],["101ms","101MS"],["154ms","154MS"],["700ms","700MS"]]]],pins:function(a){return[["A0","A0"]]},sensor:!0};confBlocks.scd40={};confBlocks.scd40.calliope={title:"SCD40",ports:[["pin","PIN1"]],pins:function(a){return[["A0","A0"]]},sensor:!0};confBlocks.scd40.calliopev3=confBlocks.scd40.calliope;confBlocks.compass={};confBlocks.compass.calliope={title:"COMPASS",ports:[["pin","PIN1"]],sensor:!0,inbuilt:!0};confBlocks.compass.microbit=confBlocks.compass.calliope; confBlocks.compass.microbitv2=confBlocks.compass.calliope;confBlocks.compass.joycar=confBlocks.compass.microbitv2;confBlocks.compass.sensebox={title:"COMPASS",sensor:!0};confBlocks.display={};confBlocks.display.spike={title:"DISPLAY",sensor:!1,inbuilt:!0};confBlocks.display.txt4=confBlocks.display.spike;confBlocks.display.rcj=confBlocks.display.spike;confBlocks.moisture={}; confBlocks.moisture.arduino={title:"MOISTURE",ports:[["S","S"]],pins:function(a){return Blockly.Blocks.robConfigDefinitions.pinsAnalog[a]},sensor:!0,standardPins:["A0"],fixedPorts:[["GND","GND"],["VCC","5V"]]};confBlocks.moisture.calliope={title:"MOISTURE",ports:[["pin","PIN1"]],pins:function(a){return[["A1","1"]]},sensor:!0};confBlocks.potentiometer={}; confBlocks.potentiometer.arduino={title:"POTENTIOMETER",ports:[["output","OUTPUT"]],pins:function(a){return Blockly.Blocks.robConfigDefinitions.pinsAnalog[a]},sensor:!0,standardPins:["A0"],fixedPorts:[["GND","GND"],["VCC","5V"]]};confBlocks.potentiometer.sensebox={title:"POTENTIOMETER",ports:[["output","OUTPUT"]],pins:function(a){return Blockly.Blocks.robConfigDefinitions.pinsAnalog[a]},sensor:!0,standardPins:["1"],fixedPorts:[["GND","GND"],["VCC","5V"]]};confBlocks.infrared={}; @@ -2663,7 +2663,7 @@ confBlocks.environmental={};confBlocks.environmental.sensebox={title:"ENVIRONMEN confBlocks.aifes={}; confBlocks.aifes.nano33ble={title:"AIFES",sensor:!1,inbuilt:!0,inputs:[["AIFES_NUMBER_INPUT_NEURONS","INPUTS"],["AIFES_NUMBER_HIDDENLAYERS_NEURONS","2"],["AIFES_NUMBER_OUTPUT_NEURONS","1"],["AIFES_FNN_LAYERS","3"],["AIFES_LEARNINGRATE","0.5"],["AIFES_MOMENTUM","0.0"],["AIFES_DATASET","1"],["AIFES_EPOCHS","1000"],["AIFES_MAX_WEIGHT","2"],["AIFES_MIN_WEIGHT","-2"]],dropdowns:[["AIFES_LEARNINGFUNCTION",[["sigmoid","sigmoid"],["relu","relu"],["softmax","softmax"],["leaky relu","leaky relu"],["elu","elu"], ["tanh","tanh"],["softsign","softsign"],["linear","linear"]]],["AIFES_OPTIMIER",[["adam","adam"],["sgd","sgd"]]],["AIFES_LOSS",[["E_mse","E_mse"],["E_crossentropy","E_crossentropy"]]],["AIFES_WEIGHT",[["init_uniform","init_uniform"],["glorot_uniform","glorot_uniform"]]]]};for(var confBlock in confBlocks){var confObj=confBlocks[confBlock];confObj.hasOwnProperty("arduino")&&(confObj.nano33ble=confObj.arduino)} -function initConfBlocks(){for(var a in confBlocks)confBlocks.hasOwnProperty(a)&&(Blockly.Blocks["robConf_"+a]={confBlock:a,init:function(){Blockly.Blocks.robConf_generic.init.call(this,confBlocks[this.confBlock][this.workspace.device],this.confBlock)}})}initConfBlocks();Blockly.Blocks.robActions={}; +function initConfBlocks(){for(var a in confBlocks)confBlocks.hasOwnProperty(a)&&(Blockly.Blocks["robConf_"+a]={confBlock:a,init:function(){var b=confBlocks[this.confBlock][this.workspace.device]||confBlocks[this.confBlock][this.workspace.subDevice]||confBlocks[this.confBlock].calliope;Blockly.Blocks.robConf_generic.init.call(this,b,this.confBlock)}})}initConfBlocks();Blockly.Blocks.robConf_scd40={confBlock:"scd40",init:function(){Blockly.Blocks.robConf_generic.init.call(this,confBlocks.scd40.calliope,this.confBlock)}};Blockly.Blocks.robActions={}; Blockly.Blocks.robActions_setLanguage={init:function(){this.setColour(Blockly.CAT_ACTION_RGB);var a=new Blockly.FieldDropdown([[Blockly.Msg.LANGUAGE_GERMAN,"GERMAN"],[Blockly.Msg.LANGUAGE_ENGLISH,"ENGLISH"],[Blockly.Msg.LANGUAGE_FRENCH,"FRENCH"],[Blockly.Msg.LANGUAGE_SPANISH,"SPANISH"],[Blockly.Msg.LANGUAGE_ITALIAN,"ITALIAN"],[Blockly.Msg.LANGUAGE_DUTCH,"DUTCH"],[Blockly.Msg.LANGUAGE_FINNISH,"FINNISH"],[Blockly.Msg.LANGUAGE_POLISH,"POLISH"],[Blockly.Msg.LANGUAGE_RUSSIAN,"RUSSIAN"],[Blockly.Msg.LANGUAGE_TURKISH, "TURKISH"],[Blockly.Msg.LANGUAGE_CZECH,"CZECH"],[Blockly.Msg.LANGUAGE_PORTUGUESE,"PORTUGUESE"],[Blockly.Msg.LANGUAGE_DANISH,"DANISH"]]);if("nao"===this.workspace.device)a=new Blockly.FieldDropdown([[Blockly.Msg.LANGUAGE_GERMAN,"GERMAN"],[Blockly.Msg.LANGUAGE_ENGLISH,"ENGLISH"],[Blockly.Msg.LANGUAGE_FRENCH,"FRENCH"],[Blockly.Msg.LANGUAGE_JAPANESE,"JAPANESE"],[Blockly.Msg.LANGUAGE_CHINESE,"CHINESE"],[Blockly.Msg.LANGUAGE_SPANISH,"SPANISH"],[Blockly.Msg.LANGUAGE_KOREAN,"KOREAN"],[Blockly.Msg.LANGUAGE_ITALIAN, "ITALIAN"],[Blockly.Msg.LANGUAGE_DUTCH,"DUTCH"],[Blockly.Msg.LANGUAGE_FINNISH,"FINNISH"],[Blockly.Msg.LANGUAGE_POLISH,"POLISH"],[Blockly.Msg.LANGUAGE_RUSSIAN,"RUSSIAN"],[Blockly.Msg.LANGUAGE_TURKISH,"TURKISH"],[Blockly.Msg.LANGUAGE_ARABIC,"ARABIC"],[Blockly.Msg.LANGUAGE_CZECH,"CZECH"],[Blockly.Msg.LANGUAGE_PORTUGUESE,"PORTUGUESE"],[Blockly.Msg.LANGUAGE_BRAZILIAN,"BRAZILIAN"],[Blockly.Msg.LANGUAGE_SWEDISH,"SWEDISH"],[Blockly.Msg.LANGUAGE_DANISH,"DANISH"],[Blockly.Msg.LANGUAGE_NORWEGIAN,"NORWEGIAN"], @@ -2884,7 +2884,7 @@ Blockly.Blocks.robCommunication_waitForConnection={init:function(){this.setColou Blockly.Blocks.robCommunication_connection={init:function(){this.setColour(Blockly.CAT_COMMUNICATION_RGB);if("nxt"===this.workspace.device){var a=new Blockly.FieldDropdown([["0 Master","0"],["1 Slave","1"],["2 Slave","2"],["3 Slave","3"]]);this.data="nxt";this.appendDummyInput().appendField(a,"CONNECTION")}this.setOutput(!0,"Connection");this.setTooltip(Blockly.Msg.CONNECTION_TOOLTIP)}}; Blockly.Blocks.robCommunication_checkConnection={init:function(){this.jsonInit({message0:Blockly.Msg.CONNECTION_CHECK,args0:[{type:"input_value",name:"CONNECTION",check:"Connection"}],output:"Boolean",colour:Blockly.CAT_COMMUNICATION_RGB,tooltip:Blockly.Msg.CONNECTION_CHECK_TOOLTIP})}};Blockly.Blocks.robCommunication_ir_sendBlock=Blockly.Blocks.bob3Communication_sendBlock;Blockly.Blocks.robCommunication_ir_receiveBlock=Blockly.Blocks.bob3Communication_receiveBlock; Blockly.Blocks.edisonCommunication_ir_sendBlock=Blockly.Blocks.bob3Communication_sendBlock;Blockly.Blocks.edisonCommunication_ir_receiveBlock=Blockly.Blocks.bob3Communication_receiveBlock;Blockly.Blocks.robConfig={}; -Blockly.Blocks.robConf_generic={init:function(a,b){this.setColour(a.sensor?Blockly.CAT_SENSOR_RGB:Blockly.CAT_ACTION_RGB);var c=a.sensor?"SENSOR_":"ACTION_",d=(Blockly.Msg[c+a.title+"_"+this.workspace.device.toUpperCase()]||Blockly.Msg[c+a.title]).charAt(0).toUpperCase()||Blockly.Msg[c+a.title]||Blockly.checkMsgKey("CONFIGURATION_PORT");a.inbuilt&&(d="_"+d);this.nameOld=d=Blockly.RobConfig.findLegalName(d,this);d=new Blockly.FieldTextInput(d,function(k){var l=this.sourceBlock_;k=k.replace(/[\s\xa0]+/g, +Blockly.Blocks.robConf_generic={init:function(a,b){this.setColour(a.sensor?Blockly.CAT_SENSOR_RGB:Blockly.CAT_ACTION_RGB);var c=a.sensor?"SENSOR_":"ACTION_",d=Blockly.Msg[c+a.title+"_"+this.workspace.device.toUpperCase()]||Blockly.Msg[c+a.title]||c+a.title;d=d.charAt(0).toUpperCase()||d||Blockly.checkMsgKey("CONFIGURATION_PORT");a.inbuilt&&(d="_"+d);this.nameOld=d=Blockly.RobConfig.findLegalName(d,this);d=new Blockly.FieldTextInput(d,function(k){var l=this.sourceBlock_;k=k.replace(/[\s\xa0]+/g, "").replace(/^ | $/g,"");if(""===k||!k.match(/^[_a-zA-Z][a-zA-Z_$0-9]*$/))return null;l.inputList.filter(function(n){return n.nameOld?n.nameOld===k:n.fieldRow[1].getText()===k});var m=l.nameOld;k=Blockly.RobConfig.findLegalName(k,l,m);Blockly.RobConfig.renameConfig(this.sourceBlock_,m,k,Blockly.Workspace.getByContainer("blocklyDiv"));return l.nameOld=k});a.inbuilt&&d.setVisible(!1);this.appendDummyInput().setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg[c+a.title+"_"+this.workspace.device.toUpperCase()]|| Blockly.Msg[c+a.title]||c+a.title,"SENSORTITLE").appendField(d,"NAME");if(a.bricks){if(Blockly.Workspace.getByContainer("bricklyDiv")){d=Blockly.getMainWorkspace().getTopBlocks(!0);var e=[];for(c=0;c extends IMbedV2Visitor { V visitHumiditySensor(HumiditySensor humiditySensor); + V visitScd40Sensor(Scd40Sensor scd40Sensor); + V visitSwitchLedMatrixAction(SwitchLedMatrixAction switchLedMatrixAction); V visitServoSetAction(ServoSetAction servoSetAction); @@ -92,4 +95,4 @@ public interface ICalliopeVisitor extends IMbedV2Visitor { V visitMoistureSensor(MoistureSensor moistureSensor); -} \ No newline at end of file +} diff --git a/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeCppVisitor.java b/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeCppVisitor.java index c04ed2f022..ec29e91151 100644 --- a/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeCppVisitor.java +++ b/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeCppVisitor.java @@ -99,6 +99,7 @@ import de.fhg.iais.roberta.syntax.sensor.generic.MoistureSensor; import de.fhg.iais.roberta.syntax.sensor.generic.PinGetValueSensor; import de.fhg.iais.roberta.syntax.sensor.generic.PinTouchSensor; +import de.fhg.iais.roberta.syntax.sensor.generic.Scd40Sensor; import de.fhg.iais.roberta.syntax.sensor.generic.SoundSensor; import de.fhg.iais.roberta.syntax.sensor.generic.TemperatureSensor; import de.fhg.iais.roberta.syntax.sensor.generic.TimerReset; @@ -178,6 +179,23 @@ public CalliopeCppVisitor(List> programPhrases, ConfigurationAst ro this.robotConfiguration = robotConfiguration; } + private boolean usesCalliopeI2c() { + return this.getBean(UsedHardwareBean.class).isActorUsed(SC.CALLIBOT) + || this.getBean(UsedHardwareBean.class).isSensorUsed(SC.COLOR) + || this.getBean(UsedHardwareBean.class).isSensorUsed(SC.SCD40); + } + + private int getCalliopeI2cBufferSize() { + int bufferSize = 0; + if ( this.getBean(UsedHardwareBean.class).isActorUsed(SC.CALLIBOT) ) { + bufferSize = Math.max(bufferSize, 5); + } + if ( this.getBean(UsedHardwareBean.class).isSensorUsed(SC.COLOR) ) { + bufferSize = Math.max(bufferSize, 8); + } + return bufferSize; + } + private static String getCallibotPin(ConfigurationComponent confComp, String port) { String portName = ""; for ( List ccList : confComp.getSubComponents().values() ) { @@ -1255,18 +1273,22 @@ private void addIncludes() { if ( this.getBean(UsedHardwareBean.class).isSensorUsed(SC.HUMIDITY) ) { this.src.add("Sht31 _sht31 = Sht31(MICROBIT_PIN_P8, MICROBIT_PIN_P2);\n"); } - if ( this.getBean(UsedHardwareBean.class).isActorUsed(SC.CALLIBOT) ) { + if ( usesCalliopeI2c() ) { this.src.add("MicroBitI2C _i2c(MICROBIT_PIN_P20, MICROBIT_PIN_P19);"); nlIndent(); - this.src.add("char _buf[5] = { 0, 0, 0, 0, 0 };"); + } + int i2cBufferSize = getCalliopeI2cBufferSize(); + if ( i2cBufferSize > 0 ) { + this.src.add("char _buf[", i2cBufferSize, "] = { ", String.join(", ", Collections.nCopies(i2cBufferSize, "0")), " };"); nlIndent(); + } + if ( this.getBean(UsedHardwareBean.class).isActorUsed(SC.CALLIBOT) ) { this.src.add("uint8_t _cbLedState = 0x00;"); } if ( this.getBean(UsedHardwareBean.class).isSensorUsed(SC.COLOR) ) { - this.src.add("MicroBitI2C _i2c(MICROBIT_PIN_P20, MICROBIT_PIN_P19);"); - nlIndent(); - this.src.add("char _buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };"); - nlIndent(); + if ( this.getBean(UsedHardwareBean.class).isActorUsed(SC.CALLIBOT) ) { + nlIndent(); + } this.src.add("std::list _TCS3472_rgb;"); nlIndent(); this.src.add("MicroBitColor _TCS3472_color;"); @@ -1579,6 +1601,26 @@ public Void visitColorSensor(ColorSensor colorSensor) { return null; } + @Override + public Void visitScd40Sensor(Scd40Sensor scd40Sensor) { + this.src.add(this.getBean(CodeGeneratorSetupBean.class).getHelperMethodGenerator().getHelperMethodName(CalliopeMethods.SCD40_GET_SAMPLE), "("); + switch ( scd40Sensor.getMode() ) { + case SC.CO2: + this.src.add("0"); + break; + case SC.TEMPERATURE: + this.src.add("1"); + break; + case SC.HUMIDITY: + this.src.add("2"); + break; + default: + throw new UnsupportedOperationException("Mode " + scd40Sensor.getMode() + " not supported!"); + } + this.src.add(")"); + return null; + } + @Override public Void visitRgbLedsOnHiddenAction(RgbLedsOnHiddenAction rgbLedsOnHiddenAction) { this.src.add("_uBit.rgb.setColour("); @@ -1639,4 +1681,4 @@ private boolean isDualMode() { Set motorPins = getMotorPins(); return motorPins.stream().filter(s -> s.equals("A") || s.equals("B")).count() > 1; } -} \ No newline at end of file +} diff --git a/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeStackMachineVisitor.java b/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeStackMachineVisitor.java index 061de3ab8c..24487e2727 100644 --- a/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeStackMachineVisitor.java +++ b/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeStackMachineVisitor.java @@ -34,6 +34,7 @@ import de.fhg.iais.roberta.syntax.sensor.generic.HumiditySensor; import de.fhg.iais.roberta.syntax.sensor.generic.InfraredSensor; import de.fhg.iais.roberta.syntax.sensor.generic.MoistureSensor; +import de.fhg.iais.roberta.syntax.sensor.generic.Scd40Sensor; import de.fhg.iais.roberta.syntax.sensor.generic.SoundSensor; import de.fhg.iais.roberta.syntax.sensor.generic.UltrasonicSensor; import de.fhg.iais.roberta.syntax.sensor.mbed.CallibotKeysSensor; @@ -186,6 +187,11 @@ public Void visitHumiditySensor(HumiditySensor humiditySensor) { return null; } + @Override + public Void visitScd40Sensor(Scd40Sensor scd40Sensor) { + return null; + } + @Override public Void visitInfraredSensor(InfraredSensor infraredSensor) { return null; diff --git a/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeV3PythonVisitor.java b/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeV3PythonVisitor.java index 6e4050426b..2115065e95 100644 --- a/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeV3PythonVisitor.java +++ b/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/codegen/CalliopeV3PythonVisitor.java @@ -45,6 +45,7 @@ import de.fhg.iais.roberta.syntax.sensor.generic.InfraredSensor; import de.fhg.iais.roberta.syntax.sensor.generic.MoistureSensor; import de.fhg.iais.roberta.syntax.sensor.generic.PinGetValueSensor; +import de.fhg.iais.roberta.syntax.sensor.generic.Scd40Sensor; import de.fhg.iais.roberta.syntax.sensor.generic.UltrasonicSensor; import de.fhg.iais.roberta.syntax.sensor.mbed.CallibotKeysSensor; import de.fhg.iais.roberta.syntax.sensor.mbed.RadioRssiSensor; @@ -581,6 +582,26 @@ public Void visitHumiditySensor(HumiditySensor humiditySensor) { return null; } + @Override + public Void visitScd40Sensor(Scd40Sensor scd40Sensor) { + this.src.add(this.getBean(CodeGeneratorSetupBean.class).getHelperMethodGenerator().getHelperMethodName(CalliopeMethods.SCD40_GET_SAMPLE), "("); + switch ( scd40Sensor.getMode() ) { + case SC.CO2: + this.src.add("0"); + break; + case SC.TEMPERATURE: + this.src.add("1"); + break; + case SC.HUMIDITY: + this.src.add("2"); + break; + default: + throw new UnsupportedOperationException("Mode " + scd40Sensor.getMode() + " not supported!"); + } + this.src.add(")"); + return null; + } + @Override public Void visitServoSetAction(ServoSetAction servoSetAction) { String port = servoSetAction.getUserDefinedPort(); diff --git a/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/validate/CalliopeCommonValidatorAndCollectorVisitor.java b/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/validate/CalliopeCommonValidatorAndCollectorVisitor.java index 1e120714e3..5891debb93 100644 --- a/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/validate/CalliopeCommonValidatorAndCollectorVisitor.java +++ b/RobotMbed/src/main/java/de/fhg/iais/roberta/visitor/validate/CalliopeCommonValidatorAndCollectorVisitor.java @@ -45,6 +45,7 @@ import de.fhg.iais.roberta.syntax.sensor.generic.InfraredSensor; import de.fhg.iais.roberta.syntax.sensor.generic.MoistureSensor; import de.fhg.iais.roberta.syntax.sensor.generic.PinGetValueSensor; +import de.fhg.iais.roberta.syntax.sensor.generic.Scd40Sensor; import de.fhg.iais.roberta.syntax.sensor.generic.SoundSensor; import de.fhg.iais.roberta.syntax.sensor.generic.UltrasonicSensor; import de.fhg.iais.roberta.syntax.sensor.mbed.CallibotKeysSensor; @@ -139,6 +140,15 @@ public Void visitHumiditySensor(HumiditySensor humiditySensor) { return null; } + @Override + public Void visitScd40Sensor(Scd40Sensor scd40Sensor) { + addToPhraseIfUnsupportedInSim(scd40Sensor, true, isSim); + checkSensorExists(scd40Sensor, SC.SCD40); + usedHardwareBuilder.addUsedSensor(new UsedSensor(scd40Sensor.getUserDefinedPort(), SC.SCD40, scd40Sensor.getMode())); + usedMethodBuilder.addUsedMethod(CalliopeMethods.SCD40_GET_SAMPLE); + return null; + } + @Override public Void visitInfraredSensor(InfraredSensor infraredSensor) { addToPhraseIfUnsupportedInSim(infraredSensor, true, isSim); @@ -469,7 +479,7 @@ protected boolean addActorMaybeCallibot(WithUserDefinedPort phrase) { protected Boolean isMotionKitPinsOverlapping() { Map usedConfig = robotConfiguration.getConfigurationComponents(); - if ( robotConfiguration.optConfigurationComponentByType(SC.CALLIBOT) != null || robotConfiguration.isComponentTypePresent("LEDBAR") || robotConfiguration.isComponentTypePresent("FOURDIGITDISPLAY") || robotConfiguration.isComponentTypePresent(SC.ULTRASONIC) || robotConfiguration.isComponentTypePresent(SC.HUMIDITY) || robotConfiguration.isComponentTypePresent(SC.COLOUR) ) { + if ( robotConfiguration.optConfigurationComponentByType(SC.CALLIBOT) != null || robotConfiguration.isComponentTypePresent("LEDBAR") || robotConfiguration.isComponentTypePresent("FOURDIGITDISPLAY") || robotConfiguration.isComponentTypePresent(SC.ULTRASONIC) || robotConfiguration.isComponentTypePresent(SC.HUMIDITY) || robotConfiguration.isComponentTypePresent(SC.COLOUR) || robotConfiguration.isComponentTypePresent(SC.SCD40) ) { return true; } for ( Map.Entry confComp : usedConfig.entrySet() ) { diff --git a/RobotMbed/src/main/java/de/fhg/iais/roberta/worker/validate/CalliopeValidatorAndCollectorWorker.java b/RobotMbed/src/main/java/de/fhg/iais/roberta/worker/validate/CalliopeValidatorAndCollectorWorker.java index 00486206e4..8fd8887781 100644 --- a/RobotMbed/src/main/java/de/fhg/iais/roberta/worker/validate/CalliopeValidatorAndCollectorWorker.java +++ b/RobotMbed/src/main/java/de/fhg/iais/roberta/worker/validate/CalliopeValidatorAndCollectorWorker.java @@ -16,7 +16,7 @@ import de.fhg.iais.roberta.visitor.validate.CommonNepoValidatorAndCollectorVisitor; public class CalliopeValidatorAndCollectorWorker extends MbedV2ValidatorAndCollectorWorker { - public static final List FREE_PINS = Stream.of("A", "B", "0", "1", "2", "3", "4", "5", "C04", "C05", "C06", "C07", "C08", "C09", "C10", "C11", "C12", "C16", "C17", "C18", "C19").collect(Collectors.toList()); + public static final List FREE_PINS = Stream.of("A", "B", "A0", "0", "1", "2", "3", "4", "5", "C04", "C05", "C06", "C07", "C08", "C09", "C10", "C11", "C12", "C16", "C17", "C18", "C19").collect(Collectors.toList()); public static final List DEFAULT_PROPERTIES = Stream.of("KEY", "ACCELEROMETER", "RGBLED", "SOUND", "COMPASS", "BUZZER", "TEMPERATURE", "GYRO", "LIGHT", "ROBOT", "LOGOTOUCH").collect(Collectors.toList()); public static final HashMap MAP_CORRECT_CONFIG_PINS = new HashMap() {{ put(SC.ULTRASONIC, "5"); diff --git a/RobotMbed/src/main/resources/calliope.methods.yml b/RobotMbed/src/main/resources/calliope.methods.yml index f06e9629c9..0bd09f77f4 100644 --- a/RobotMbed/src/main/resources/calliope.methods.yml +++ b/RobotMbed/src/main/resources/calliope.methods.yml @@ -147,3 +147,100 @@ GET_ROTATION: if factor != 0: pitch = math.atan(-x / (factor)) return math.floor((360*pitch)/(2*math.pi)) + +SCD40_GET_SAMPLE: + PYTHON: | + def scd40_get_sample(mode): + global _scd40_i2c_initialized, _scd40_started, _scd40_values + try: + _scd40_started + except NameError: + _scd40_i2c_initialized = False + _scd40_started = False + _scd40_values = (0, 0, 0) + + def scd40_crc(data): + crc = 0xff + for byte in data: + crc ^= byte + for _ in range(8): + if crc & 0x80: + crc = ((crc << 1) ^ 0x31) & 0xff + else: + crc = (crc << 1) & 0xff + return crc + + if not _scd40_i2c_initialized: + try: + if hasattr(calliopemini, "pin_A0_SCL") and hasattr(calliopemini, "pin_A0_SDA"): + calliopemini.i2c.init(freq=400000, scl=calliopemini.pin_A0_SCL, sda=calliopemini.pin_A0_SDA) + elif hasattr(calliopemini, "pin_C19") and hasattr(calliopemini, "pin_C20"): + calliopemini.i2c.init(freq=400000, scl=calliopemini.pin_C19, sda=calliopemini.pin_C20) + except Exception: + pass + _scd40_i2c_initialized = True + + try: + if not _scd40_started: + calliopemini.i2c.write(0x62, b'\x21\xb1') + calliopemini.sleep(5000) + _scd40_started = True + + calliopemini.i2c.write(0x62, b'\xec\x05') + calliopemini.sleep(1) + data = calliopemini.i2c.read(0x62, 9) + except Exception: + return _scd40_values[mode] + + if len(data) >= 9 and scd40_crc(data[0:2]) == data[2] and scd40_crc(data[3:5]) == data[5] and scd40_crc(data[6:8]) == data[8]: + co2 = (data[0] << 8) | data[1] + raw_temperature = (data[3] << 8) | data[4] + raw_humidity = (data[6] << 8) | data[7] + _scd40_values = (co2, -45 + 175 * raw_temperature / 65535, 100 * raw_humidity / 65535) + + return _scd40_values[mode] + C: | + double scd40_get_sample(int mode) { + static bool started = false; + static double values[3] = { 0, 0, 0 }; + const int address = 0x62 << 1; + if ( !started ) { + char startCommand[2] = { 0x21, (char) 0xb1 }; + _i2c.write(address, startCommand, 2); + _uBit.sleep(5000); + started = true; + } + + char readCommand[2] = { (char) 0xec, 0x05 }; + char data[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + _i2c.write(address, readCommand, 2); + _uBit.sleep(1); + if ( _i2c.read(address, data, 9) == 0 ) { + bool crcValid = true; + for ( int word = 0; word < 3; word++ ) { + uint8_t crc = 0xff; + for ( int i = 0; i < 2; i++ ) { + crc ^= (uint8_t) data[word * 3 + i]; + for ( int bit = 0; bit < 8; bit++ ) { + if ( crc & 0x80 ) { + crc = (uint8_t) ((crc << 1) ^ 0x31); + } else { + crc = (uint8_t) (crc << 1); + } + } + } + if ( crc != (uint8_t) data[word * 3 + 2] ) { + crcValid = false; + } + } + if ( crcValid ) { + uint16_t co2 = ((uint8_t) data[0] << 8) | (uint8_t) data[1]; + uint16_t rawTemperature = ((uint8_t) data[3] << 8) | (uint8_t) data[4]; + uint16_t rawHumidity = ((uint8_t) data[6] << 8) | (uint8_t) data[7]; + values[0] = co2; + values[1] = -45.0 + 175.0 * rawTemperature / 65535.0; + values[2] = 100.0 * rawHumidity / 65535.0; + } + } + return values[mode]; + } diff --git a/RobotMbed/src/main/resources/calliope/configuration.toolbox.xml b/RobotMbed/src/main/resources/calliope/configuration.toolbox.xml index cafcd443e9..d5d4b5c31c 100644 --- a/RobotMbed/src/main/resources/calliope/configuration.toolbox.xml +++ b/RobotMbed/src/main/resources/calliope/configuration.toolbox.xml @@ -77,5 +77,6 @@ + - \ No newline at end of file + diff --git a/RobotMbed/src/main/resources/calliope/program.toolbox.beginner.xml b/RobotMbed/src/main/resources/calliope/program.toolbox.beginner.xml index 278fd03434..7baf76fbc5 100644 --- a/RobotMbed/src/main/resources/calliope/program.toolbox.beginner.xml +++ b/RobotMbed/src/main/resources/calliope/program.toolbox.beginner.xml @@ -39,6 +39,7 @@ + diff --git a/RobotMbed/src/main/resources/calliope/program.toolbox.expert.xml b/RobotMbed/src/main/resources/calliope/program.toolbox.expert.xml index 7d08885359..b01c68062f 100644 --- a/RobotMbed/src/main/resources/calliope/program.toolbox.expert.xml +++ b/RobotMbed/src/main/resources/calliope/program.toolbox.expert.xml @@ -203,6 +203,7 @@ + diff --git a/RobotMbed/src/main/resources/calliopeV3/configuration.toolbox.xml b/RobotMbed/src/main/resources/calliopeV3/configuration.toolbox.xml index cafcd443e9..d5d4b5c31c 100644 --- a/RobotMbed/src/main/resources/calliopeV3/configuration.toolbox.xml +++ b/RobotMbed/src/main/resources/calliopeV3/configuration.toolbox.xml @@ -77,5 +77,6 @@ + - \ No newline at end of file + diff --git a/RobotMbed/src/main/resources/calliopeV3/program.toolbox.beginner.xml b/RobotMbed/src/main/resources/calliopeV3/program.toolbox.beginner.xml index 0bd563703e..49fb025b16 100644 --- a/RobotMbed/src/main/resources/calliopeV3/program.toolbox.beginner.xml +++ b/RobotMbed/src/main/resources/calliopeV3/program.toolbox.beginner.xml @@ -40,6 +40,7 @@ + diff --git a/RobotMbed/src/main/resources/calliopeV3/program.toolbox.expert.xml b/RobotMbed/src/main/resources/calliopeV3/program.toolbox.expert.xml index 39d1716094..a51644bcdb 100644 --- a/RobotMbed/src/main/resources/calliopeV3/program.toolbox.expert.xml +++ b/RobotMbed/src/main/resources/calliopeV3/program.toolbox.expert.xml @@ -213,6 +213,7 @@ +