diff options
-rw-r--r-- | Firmware/Arduino/pidmata3/pidmata3.ino | 12 | ||||
-rwxr-xr-x | Resources/Library/linux64/libmodelPlugFirmata.so | bin | 56334 -> 56374 bytes | |||
-rwxr-xr-x | Source/libmodelPlugFirmata.so | bin | 56334 -> 56374 bytes | |||
-rw-r--r--[-rwxr-xr-x] | Source/modelPlugFirmata.cpp | 11 | ||||
-rwxr-xr-x | Source/modelPlugFirmata.cpp~ | 680 | ||||
-rw-r--r-- | package.mo | 78 |
6 files changed, 761 insertions, 20 deletions
diff --git a/Firmware/Arduino/pidmata3/pidmata3.ino b/Firmware/Arduino/pidmata3/pidmata3.ino index 01a4710..3cfadbc 100644 --- a/Firmware/Arduino/pidmata3/pidmata3.ino +++ b/Firmware/Arduino/pidmata3/pidmata3.ino @@ -28,11 +28,11 @@ #include <Firmata.h> #include <AutoPID.h> -//Comment the line below, "#define PID", if you are not using PID else uncomment it and follow further instructions. +//Comment the macro defined below "#define PID" if you are not using PID, else uncomment it and follow further instructions. #define PID //------------PID values---------------- -// Pin 6 - setPoint (input value) +// Pin 6 - setPoint (input value) // Pin 5 - feedback (input value) // Pin 15 - control (output value) @@ -40,14 +40,14 @@ //If you use both real will be prefered //#define REAL_INPUT // This line define analog pin for read values from real sources -#define AREAD_PIN A1 +#define AREAD_PIN A2 #define PID_OUTPUT_MIN -512.0 #define PID_OUTPUT_MAX 512.0 -#define PID_KP 15 -#define PID_KI 10 -#define PID_KD 10 +#define PID_KP 5 +#define PID_KI 3 +#define PID_KD 3 #define PID_BANG_BANG 40 #define PID_INTERVAL 100 diff --git a/Resources/Library/linux64/libmodelPlugFirmata.so b/Resources/Library/linux64/libmodelPlugFirmata.so Binary files differindex 22d3c01..3e71a82 100755 --- a/Resources/Library/linux64/libmodelPlugFirmata.so +++ b/Resources/Library/linux64/libmodelPlugFirmata.so diff --git a/Source/libmodelPlugFirmata.so b/Source/libmodelPlugFirmata.so Binary files differindex 22d3c01..3e71a82 100755 --- a/Source/libmodelPlugFirmata.so +++ b/Source/libmodelPlugFirmata.so diff --git a/Source/modelPlugFirmata.cpp b/Source/modelPlugFirmata.cpp index cd4441e..8ad53cf 100755..100644 --- a/Source/modelPlugFirmata.cpp +++ b/Source/modelPlugFirmata.cpp @@ -21,6 +21,7 @@ #include <stdint.h> #include <algorithm> #include <vector> +#include <cmath> #include "serial.h" #include "modelPlugFirmata.h" @@ -81,7 +82,7 @@ public: void writeDigitalPin(uint32_t pin,uint32_t value); void writeAnalogPin(uint32_t pin, uint32_t value); void writeServoPin(uint32_t pin, uint32_t value, int min, int max); - double readAnalogPin(uint32_t pin, double min, double max, double init); + double readAnalogPin(uint32_t pin, double min, double max, double init, int adcResolution); uint32_t readDigitalPin(uint32_t pin, int init); void setServoConfig(uint32_t pin,uint32_t min,uint32_t max); @@ -244,12 +245,12 @@ void firmataBoard::writeServoPin(uint32_t pin, uint32_t value, int min, int max) } } -double firmataBoard::readAnalogPin(uint32_t pin,double min, double max, double init){ +double firmataBoard::readAnalogPin(uint32_t pin,double min, double max, double init, int adcResolution){ if(ready){ if(pin_info[pin].mode!=MODE_ANALOG) setPinMode(pin,MODE_ANALOG); if(pin_info[pin].ready) - return min+((pin_info[pin].value/1023.0)*(max-min)); + return min+((pin_info[pin].value/(pow(2, adcResolution)-1))*(max-min)); else return init; } @@ -652,9 +653,9 @@ EXPORT int getBoardId(void* object){ return -1; } -EXPORT double readAnalogPin(int pin, double min, double max, double init, int id){ +EXPORT double readAnalogPin(int pin, double min, double max, double init, int id, int adcResolution){ firmataBoard* board = firmataBoardHandler::instance()->getBoard(id); - double value = board->readAnalogPin(pin,min,max,init); + double value = board->readAnalogPin(pin,min,max,init, adcResolution); return value; } EXPORT int readDigitalPin(int pin, int init, int id){ diff --git a/Source/modelPlugFirmata.cpp~ b/Source/modelPlugFirmata.cpp~ new file mode 100755 index 0000000..011ca40 --- /dev/null +++ b/Source/modelPlugFirmata.cpp~ @@ -0,0 +1,680 @@ + +/* ModelPlug: Modelica connection to Firmata + * Author: Leonardo Laguna Ruiz + * Based on Firmata GUI-friendly queries test by Paul Stoffregen (paul@pjrc.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdint.h> +#include <algorithm> +#include <vector> + +#include "serial.h" +#include "modelPlugFirmata.h" + + +typedef struct { + uint8_t mode; + uint8_t analog_channel; + uint64_t supported_modes; + uint32_t value; + uint32_t next_value; + uint8_t ready; +} pin_t; + +#define MODE_INPUT 0x00 +#define MODE_OUTPUT 0x01 +#define MODE_ANALOG 0x02 +#define MODE_PWM 0x03 +#define MODE_SERVO 0x04 +#define MODE_SHIFT 0x05 +#define MODE_I2C 0x06 + +#define START_SYSEX 0xF0 // start a MIDI Sysex message +#define END_SYSEX 0xF7 // end a MIDI Sysex message +#define PIN_MODE_QUERY 0x72 // ask for current and supported pin modes +#define PIN_MODE_RESPONSE 0x73 // reply with current and supported pin modes + +#define RESERVED_COMMAND 0x00 // 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc). +#define ANALOG_MAPPING_QUERY 0x69 // ask for mapping of analog to pin numbers +#define ANALOG_MAPPING_RESPONSE 0x6A // reply with mapping info +#define CAPABILITY_QUERY 0x6B // ask for supported modes and resolution of all pins +#define CAPABILITY_RESPONSE 0x6C // reply with supported modes and resolution +#define PIN_STATE_QUERY 0x6D // ask for a pin's current mode and value +#define PIN_STATE_RESPONSE 0x6E // reply with a pin's current mode and value +#define EXTENDED_ANALOG 0x6F // analog write (PWM, Servo, etc) to any pin +#define SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq +#define STRING_DATA 0x71 // a string message with 14-bits per char +#define SHIFT_DATA 0x75 // shiftOut config/data message (34 bits) +#define I2C_REQUEST 0x76 // I2C request messages from a host to an I/O board +#define I2C_REPLY 0x77 // I2C reply messages from an I/O board to a host +#define I2C_CONFIG 0x78 // Configure special I2C settings such as power pins and delay times +#define REPORT_FIRMWARE 0x79 // report name and version of the firmware +#define SAMPLING_INTERVAL 0x7A // sampling interval +#define SYSEX_NON_REALTIME 0x7E // MIDI Reserved for non-realtime messages +#define SYSEX_REALTIME 0x7F // MIDI Reserved for realtime messages + +class firmataBoard +{ +public: + firmataBoard(std::string port = "dummy",bool showCapabilitites=false,int samplingMs=10,int baudRate=57600,bool fake=true); + ~firmataBoard(){}; + + std::string getPortName(); + int openPort(); + void closePort(); + std::vector<std::string> getPortList(); + void setPinMode(uint32_t pin, uint32_t mode); + void writeDigitalPin(uint32_t pin,uint32_t value); + void writeAnalogPin(uint32_t pin, uint32_t value); + void writeServoPin(uint32_t pin, uint32_t value, int min, int max); + double readAnalogPin(uint32_t pin, double min, double max, double init); + uint32_t readDigitalPin(uint32_t pin, int init); + void setServoConfig(uint32_t pin,uint32_t min,uint32_t max); + +public: + void initialize(bool dtr); + void updateBoard(int timeout); + void reportFirmware(); + void showPinCapabilities(); + void setSamplingInterval(); + void setAsFakePort(); +private: + + int write(const void *ptr, int len); + int read(void *ptr, int count,int timeout); + void Parse(const uint8_t *buf, int len); + void DoMessage(void); + + pin_t pin_info[128]; + std::string port_name; + bool show_capabilitites; + int sampling; + int baudrate; + Serial serial_port; + bool ready; + bool is_fake_port; + + + std::string firmata_name; + int parse_count; + int parse_command_len; + uint8_t parse_buf[4096]; +}; + +// This is an external object that we want to use in our modelica code. +class firmataBoardHandler { + firmataBoardHandler(){ + try + { + std::vector<std::string> available_ports = dummyPort.getPortList(); + printf("[ModelPlug.Firmata]: Available ports:\n"); fflush(stdout); + for (std::vector<std::string>::iterator it = available_ports.begin() ; it != available_ports.end(); ++it){ + printf("- %s\n",(*it).c_str());fflush(stdout); + } + } + catch(std::exception&) + { + printf("[ModelPlug.Firmata]: Failed to show the port names\n");fflush(stdout); + } + } + +public: + static firmataBoardHandler *instance() + { + if (!s_instance) + s_instance = new firmataBoardHandler; + return s_instance; + } + firmataBoard* registerBoard(char* port,bool showCapabilitites,int samplingMs,int baudRate,bool dtr); + int getPortIndex(firmataBoard* elem); + + firmataBoard* getBoard(uint32_t id); + +private: + std::vector<firmataBoard*> ports; + + firmataBoard dummyPort; + + static firmataBoardHandler *s_instance; + +}; + +firmataBoardHandler *firmataBoardHandler::s_instance = 0; + +int firmataBoard::write(const void *ptr, int len){ + if(!is_fake_port) return serial_port.Write(ptr,len); + return 0; +} + +int firmataBoard::read(void *ptr, int count, int timeout){ + if(!is_fake_port){ + if (serial_port.Is_open() && (serial_port.Input_wait(timeout)>0)) + return serial_port.Read(ptr, count); + return 0; + } + return 0; +} + +void firmataBoard::setAsFakePort(){ + is_fake_port = true; +} + +firmataBoard::firmataBoard(std::string port, bool showCapabilitites, int samplingMs, int baudRate, bool fake) + :port_name(port),show_capabilitites(showCapabilitites),sampling(samplingMs),baudrate(baudRate),is_fake_port(fake){ + // Initialize the pin information + for (int i=0; i < 128; i++) { + pin_info[i].mode = 255; + pin_info[i].analog_channel = 127; + pin_info[i].supported_modes = 0; + pin_info[i].value = 0; + pin_info[i].next_value = 0; + pin_info[i].ready = 0; + } + ready = false; +} + +void firmataBoard::setPinMode(uint32_t pin, uint32_t mode){ + + if (mode != pin_info[pin].mode && ready) { + // send the mode change message + uint8_t buf[4]; + buf[0] = 0xF4; + buf[1] = pin; + buf[2] = mode; + write(buf, 3); + pin_info[pin].mode = mode; + pin_info[pin].value = 0; + pin_info[pin].next_value = 0; + printf("[ModelPlug.Firmata]: %s setting pin %i to mode %i\n",port_name.c_str(),pin,mode); + } +} + +void firmataBoard::setServoConfig(uint32_t pin,uint32_t min,uint32_t max){ + if(ready){ + uint8_t buf[8]; + buf[0] = START_SYSEX; + buf[1] = SERVO_CONFIG; + buf[2] = pin; + buf[3] = min & 0x7F; + buf[4] = (min >> 7) & 0x7F; + buf[5] = max & 0x7F; + buf[6] = (max >> 7) & 0x7F; + buf[7] = END_SYSEX; + write(buf, 8); + } +} + +void firmataBoard::writeDigitalPin(uint32_t pin,uint32_t value){ + if(ready){ + if(pin_info[pin].mode!=MODE_OUTPUT) + setPinMode(pin,MODE_OUTPUT); + pin_info[pin].next_value = value; + } +} + +void firmataBoard::writeAnalogPin(uint32_t pin, uint32_t value){ + if(ready){ + if(pin_info[pin].mode!=MODE_PWM) + setPinMode(pin,MODE_PWM); + pin_info[pin].next_value = value; + } +} + +void firmataBoard::writeServoPin(uint32_t pin, uint32_t value, int min, int max){ + if(ready){ + if(pin_info[pin].mode!=MODE_SERVO){ + setPinMode(pin,MODE_SERVO); + setServoConfig(pin,min,max); + } + pin_info[pin].next_value = value; + } +} + +double firmataBoard::readAnalogPin(uint32_t pin,double min, double max, double init, int adcResolution){ + if(ready){ + if(pin_info[pin].mode!=MODE_ANALOG) + setPinMode(pin,MODE_ANALOG); + if(pin_info[pin].ready) + return min+((pin_info[pin].value/pow(2, adcResolution)-1)*(max-min)); + else + return init; + } + return init; +} + +uint32_t firmataBoard::readDigitalPin(uint32_t pin, int init){ + if(ready){ + if(pin_info[pin].mode!=MODE_INPUT) + setPinMode(pin,MODE_INPUT); + if(pin_info[pin].ready) + return pin_info[pin].value; + else + return init; + } + return init; +} + +void firmataBoard::reportFirmware(){ + uint8_t buf[3]; + buf[0] = START_SYSEX; + buf[1] = REPORT_FIRMWARE; // read firmata name & version + buf[2] = END_SYSEX; + write(buf, 3); +} + +void firmataBoard::setSamplingInterval(){ + uint8_t buf[5]; + buf[0] = START_SYSEX; + buf[1] = SAMPLING_INTERVAL; // read firmata name & version + buf[2] = sampling & 0x7F; + buf[3] = (sampling >> 7) & 0x7F; + buf[4] = END_SYSEX; + write(buf, 5); + printf("[ModelPlug.Firmata]: Setting sampling interval to %i ms for board %s\n",sampling,port_name.c_str()); fflush(stdout); +} + +void firmataBoard::showPinCapabilities(){ + printf("[ModelPlug.Firmata]: Board %s capabilities\n", port_name.c_str()); + for (int pin=0; pin<128; pin++) { + if(pin_info[pin].supported_modes!=0){ + printf("- Pin %i supports: ",pin); + if (pin_info[pin].supported_modes & (1<<MODE_INPUT)) printf(" DigitalInput"); + if (pin_info[pin].supported_modes & (1<<MODE_OUTPUT)) printf(" - DigitalOutput"); + if (pin_info[pin].supported_modes & (1<<MODE_ANALOG)) printf(" - AnalogInput(A%d)",pin_info[pin].analog_channel); + if (pin_info[pin].supported_modes & (1<<MODE_PWM)) printf(" - AnalogOutput"); + if (pin_info[pin].supported_modes & (1<<MODE_SERVO)) printf(" - Servo"); + printf("\n"); + } + } + fflush(stdout); +} + +void firmataBoard::updateBoard(int timeout){ + uint8_t buf[1024]; + int r; + // write the output values + if(ready) + for (int pin=0; pin<128; pin++) { + if(pin_info[pin].value!=pin_info[pin].next_value && (pin_info[pin].mode==MODE_OUTPUT || pin_info[pin].mode==MODE_PWM || pin_info[pin].mode==MODE_SERVO)){ + + pin_info[pin].value=pin_info[pin].next_value; + + // Digital output + if(pin_info[pin].mode==MODE_OUTPUT){ + int port_num = pin / 8; + int port_val = 0; + for (int i=0; i<8; i++) { + int p = port_num * 8 + i; + if (pin_info[p].mode == MODE_OUTPUT || pin_info[p].mode == MODE_INPUT) { + if (pin_info[p].value) { + port_val |= (1<<i); + } + } + } + uint8_t buf[3]; + buf[0] = 0x90 | port_num; + buf[1] = port_val & 0x7F; + buf[2] = (port_val >> 7) & 0x7F; + write(buf, 3); + } + // Analog output or servo + if(pin_info[pin].mode==MODE_PWM || pin_info[pin].mode==MODE_SERVO){ + uint32_t value = pin_info[pin].value; + + if (pin <= 15 && value <= 16383) { + uint8_t buf[3]; + buf[0] = 0xE0 | pin; + buf[1] = value & 0x7F; + buf[2] = (value >> 7) & 0x7F; + write(buf, 3); + } else { + uint8_t buf[12]; + int len=4; + buf[0] = 0xF0; + buf[1] = 0x6F; + buf[2] = pin; + buf[3] = value & 0x7F; + if (value > 0x00000080) buf[len++] = (value >> 7) & 0x7F; + if (value > 0x00004000) buf[len++] = (value >> 14) & 0x7F; + if (value > 0x00200000) buf[len++] = (value >> 21) & 0x7F; + if (value > 0x10000000) buf[len++] = (value >> 28) & 0x7F; + buf[len++] = 0xF7; + write(buf, len); + } + } + } + } + // receieve bytes from the serial port + r = read(buf, sizeof(buf),timeout); + if (r) { + Parse(buf, r); + } +} + +void firmataBoard::Parse(const uint8_t *buf, int len) +{ + const uint8_t *p, *end; + + p = buf; + end = p + len; + for (p = buf; p < end; p++) { + uint8_t msn = *p & 0xF0; + if (msn == 0xE0 || msn == 0x90 || *p == 0xF9) { + parse_command_len = 3; + parse_count = 0; + } else if (msn == 0xC0 || msn == 0xD0) { + parse_command_len = 2; + parse_count = 0; + } else if (*p == START_SYSEX) { + parse_count = 0; + parse_command_len = sizeof(parse_buf); + } else if (*p == END_SYSEX) { + parse_command_len = parse_count + 1; + } else if (*p & 0x80) { + parse_command_len = 1; + parse_count = 0; + } + if (parse_count < (int)sizeof(parse_buf)) { + parse_buf[parse_count++] = *p; + } + if (parse_count == parse_command_len) { + DoMessage(); + parse_count = parse_command_len = 0; + } + } +} + +void firmataBoard::DoMessage(void) +{ + uint8_t cmd = (parse_buf[0] & 0xF0); + + if (cmd == 0xE0 && parse_count == 3) { + int analog_ch = (parse_buf[0] & 0x0F); + int analog_val = parse_buf[1] | (parse_buf[2] << 7); + for (int pin=0; pin<128; pin++) { + if (pin_info[pin].analog_channel == analog_ch) { + pin_info[pin].value = analog_val; + pin_info[pin].ready = 1; + return; + } + } + return; + } + if (cmd == 0x90 && parse_count == 3) { + int port_num = (parse_buf[0] & 0x0F); + int port_val = parse_buf[1] | (parse_buf[2] << 7); + int pin = port_num * 8; + //printf("port_num = %d, port_val = %d\n", port_num, port_val); + for (int mask=1; mask & 0xFF; mask <<= 1, pin++) { + if (pin_info[pin].mode == MODE_INPUT) { + uint32_t val = (port_val & mask) ? 1 : 0; + if (pin_info[pin].value != val) { + pin_info[pin].value = val; + pin_info[pin].ready = 1; + } + } + } + return; + } + + + if (parse_buf[0] == START_SYSEX && parse_buf[parse_count-1] == END_SYSEX) { + // Sysex message + if (parse_buf[1] == REPORT_FIRMWARE) { + char name[140]; + int len=0; + for (int i=4; i < parse_count-2; i+=2) { + name[len++] = (parse_buf[i] & 0x7F) + | ((parse_buf[i+1] & 0x7F) << 7); + } + name[len++] = '-'; + name[len++] = parse_buf[2] + '0'; + name[len++] = '.'; + name[len++] = parse_buf[3] + '0'; + name[len++] = 0; + firmata_name = name; + printf("[ModelPlug.Firmata]: %s %s\n",port_name.c_str(),name); + ready = true; + // query the board's capabilities only after hearing the + // REPORT_FIRMWARE message. For boards that reset when + // the port open (eg, Arduino with reset=DTR), they are + // not ready to communicate for some time, so the only + // way to reliably query their capabilities is to wait + // until the REPORT_FIRMWARE message is heard. + uint8_t buf[80]; + len=0; + buf[len++] = START_SYSEX; + buf[len++] = ANALOG_MAPPING_QUERY; // read analog to pin # info + buf[len++] = END_SYSEX; + buf[len++] = START_SYSEX; + buf[len++] = CAPABILITY_QUERY; // read capabilities + buf[len++] = END_SYSEX; + for (int i=0; i<16; i++) { + buf[len++] = 0xC0 | i; // report analog + buf[len++] = 1; + buf[len++] = 0xD0 | i; // report digital + buf[len++] = 1; + } + write(buf, len); + setSamplingInterval(); + } else if (parse_buf[1] == CAPABILITY_RESPONSE) { + int pin, i, n; + for (pin=0; pin < 128; pin++) { + pin_info[pin].supported_modes = 0; + } + for (i=2, n=0, pin=0; i<parse_count; i++) { + if (parse_buf[i] == 127) { + pin++; + n = 0; + continue; + } + if (n == 0) { + // first byte is supported mode + pin_info[pin].supported_modes |= (1<<parse_buf[i]); + } + n = n ^ 1; + } + if(show_capabilitites) { + showPinCapabilities(); + show_capabilitites = false; + } + // send a state query for for every pin with any modes + for (pin=0; pin < 128; pin++) { + uint8_t buf[512]; + int len=0; + if (pin_info[pin].supported_modes) { + buf[len++] = START_SYSEX; + buf[len++] = PIN_STATE_QUERY; + buf[len++] = pin; + buf[len++] = END_SYSEX; + } + write(buf, len); + } + } else if (parse_buf[1] == ANALOG_MAPPING_RESPONSE) { + int pin=0; + for (int i=2; i<parse_count-1; i++) { + pin_info[pin].analog_channel = parse_buf[i]; + pin++; + } + return; + } else if (parse_buf[1] == PIN_STATE_RESPONSE && parse_count >= 6) { + int pin = parse_buf[2]; + pin_info[pin].mode = parse_buf[3]; + pin_info[pin].value = parse_buf[4]; + if (parse_count > 6) pin_info[pin].value |= (parse_buf[5] << 7); + if (parse_count > 7) pin_info[pin].value |= (parse_buf[6] << 14); + //add_pin(pin); + } + return; + } +} + +std::vector<std::string> firmataBoard::getPortList(){ + return serial_port.port_list(); +} + +firmataBoard* firmataBoardHandler::getBoard(uint32_t id){ + if(id<0) + return &dummyPort; + else + return ports[id]; +} + +firmataBoard* firmataBoardHandler::registerBoard(char* port,bool showCapabilitites,int samplingMs,int baudRate,bool dtr){ + + // Check if the port exists + bool port_exists = false; + bool fake_port = false; + std::string port_name(port); + std::vector<std::string> available_ports = dummyPort.getPortList(); + for (std::vector<std::string>::iterator it = available_ports.begin() ; it != available_ports.end(); ++it){ + if((*it).compare(port_name)==0){ + port_exists = true; + break; + } + } + + if(!port_exists) { + printf("[ModelPlug.Firmata]: ERROR The port %s does not exist\n",port); fflush(stdout); + fake_port |= true; + } + + // Check if the port is already used + for (std::vector<firmataBoard*>::iterator it = ports.begin() ; it != ports.end(); ++it){ + if ((*it)->getPortName().compare(port_name)==0) + { + // Print duplicated port, report error + printf("[ModelPlug.Firmata]: ERROR: Trying to use two boards with the port %s\n",port);fflush(stdout); + fake_port |= true; + } + } + + firmataBoard* new_port = new firmataBoard(port_name,showCapabilitites,samplingMs,baudRate,fake_port); + + if(new_port->openPort()==0){ + ports.push_back(new_port); + new_port->initialize(dtr); + return new_port; + } + else{ + // Could not open the port return error + printf("[ModelPlug.Firmata]: ERROR Failed to open the port %s\n",port); fflush(stdout); + new_port->setAsFakePort(); + return new_port; + } + return new_port; +} + +int firmataBoardHandler::getPortIndex(firmataBoard* elem) { + unsigned pos = std::find(ports.begin(), ports.end(), elem) - ports.begin(); + if(pos >= ports.size()){ // not found + return -1; + } + return pos; +} + +std::string firmataBoard::getPortName(){ + return port_name; +} + +int firmataBoard::openPort(){ + if(is_fake_port){ + return 0; + } else { + serial_port.Open(port_name); + serial_port.Set_baud(baudrate); + if(serial_port.Is_open()){ + printf("[ModelPlug.Firmata]: Using port %s with baud rate %i\n",port_name.c_str(),baudrate); fflush(stdout); + return 0; + } + else + return -1; + } + return -1; +} + +void firmataBoard::initialize(bool dtr){ + serial_port.Set_control(dtr?1:0,-1); + updateBoard(5); + reportFirmware(); + updateBoard(5); +} + +void firmataBoard::closePort(){ + if(is_fake_port) return; + else + if(serial_port.Is_open()) + serial_port.Close(); +} + +extern "C" + +{ + + +EXPORT void* boardConstructor(char* port,bool showCapabilitites,int samplingMs,int baudRate,bool dtr){ + firmataBoardHandler* boards = firmataBoardHandler::instance(); + void* object = (void*)boards->registerBoard(port,showCapabilitites,samplingMs,baudRate,dtr); + return object; +} +EXPORT void boardDestructor(void* object){ + if(object!=NULL){ + firmataBoard* board = (firmataBoard*)object; + board->closePort(); + delete board; + } +} + +EXPORT void updateBoard(int id){ + firmataBoard* board = firmataBoardHandler::instance()->getBoard(id); + board->updateBoard(0); +} + +EXPORT int getBoardId(void* object){ + if(object!=NULL){ + return firmataBoardHandler::instance()->getPortIndex((firmataBoard*)object); + } + else + return -1; +} + +EXPORT double readAnalogPin(int pin, double min, double max, double init, int id, int adcResolution){ + firmataBoard* board = firmataBoardHandler::instance()->getBoard(id); + double value = board->readAnalogPin(pin,min,max,init, adcResolution); + return value; +} +EXPORT int readDigitalPin(int pin, int init, int id){ + firmataBoard* board = firmataBoardHandler::instance()->getBoard(id); + int value = board->readDigitalPin(pin,init); + return value; +} +EXPORT void writeAnalogPin(int pin, int id,double value){ + double croped = value>1.0?1.0:(value<0.0?0.0:value); + firmataBoard* board = firmataBoardHandler::instance()->getBoard(id); + board->writeAnalogPin(pin,(uint32_t)(croped*1023)); +} +EXPORT void writeDigitalPin(int pin, int id,int value){ + firmataBoard* board = firmataBoardHandler::instance()->getBoard(id); + board->writeDigitalPin(pin,value); +} +EXPORT void writeServoPin(int pin, int id,double value,int min,int max){ + double croped = value>1.0?1.0:(value<0.0?0.0:value); + firmataBoard* board = firmataBoardHandler::instance()->getBoard(id); + board->writeServoPin(pin,(int)(croped*180),min,max); +} + +} // end extern "C" @@ -264,6 +264,7 @@ equation annotation(Icon(coordinateSystem( initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(fillColor = {0, 85, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-95, 90}, {95, -70}}, radius = 10), Text(origin = {0, 20}, lineColor = {255, 255, 255}, extent = {{-85, 40}, {85, -40}}, textString = "%BoardName"), Text(origin = {0, -80}, extent = {{-50, 20}, {50, -20}}, textString = "Port: %Port")}), Diagram(coordinateSystem( initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(fillColor = {0, 85, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-95, 80}, {95, -80}}, radius = 10), Text( lineColor = {255, 255, 255}, extent = {{-85, 35}, {85, -35}}, textString = "%BoardName")})); end customBoard; + annotation(Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Polygon(visible = true, origin = {12.096, 9.352}, fillColor = {0, 128, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{-85.75100000000001, 70.648}, {-102.737, 66.761}, {-105.751, 50.648}, {-105.751, -69.352}, {-99.47499999999999, -85.465}, {-85.75100000000001, -89.352}, {74.249, -89.352}, {81.746, -83.29000000000001}, {86.32899999999999, -74.352}, {84.249, 34.141}, {82.185, 50.648}, {74.732, 67.486}, {52.373, 70.648}, {31.729, 70.648}}, smooth = Smooth.Bezier), Rectangle(visible = true, origin = {-69.67700000000001, 40}, fillColor = {106, 108, 116}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-32.24, -20}, {32.24, 20}}, radius = 10), Rectangle(visible = true, origin = {-77.83199999999999, -45.041}, fillPattern = FillPattern.Solid, extent = {{-25.915, -15.041}, {25.915, 15.041}}, radius = 10), Rectangle(visible = true, origin = {24.177, 70}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-54.177, -6.186}, {54.177, 6.186}}, radius = 10), Rectangle(visible = true, origin = {23.906, -63.814}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-64.17700000000001, -6.186}, {64.17700000000001, 6.186}}, radius = 10), Rectangle(visible = true, origin = {21.91, 0}, fillPattern = FillPattern.Solid, extent = {{-28.09, -25}, {28.09, 25}}, radius = 10), Rectangle(visible = true, origin = {78.083, -63.624}, fillColor = {250, 105, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {68.083, -63.624}, fillColor = {243, 134, 48}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {58.083, -63.624}, fillColor = {250, 105, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {48.083, -63.624}, fillColor = {243, 134, 48}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {38.083, -63.624}, fillColor = {250, 105, 0}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {28.083, -63.624}, fillColor = {243, 134, 48}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {70.00100000000001, 70}, fillColor = {167, 219, 216}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {60.001, 70}, fillColor = {105, 210, 231}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {50.001, 70}, fillColor = {167, 219, 216}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {40.001, 70}, fillColor = {105, 210, 231}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {30.001, 70}, fillColor = {167, 219, 216}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {20.001, 70}, fillColor = {105, 210, 231}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {10.001, 70}, fillColor = {167, 219, 216}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {0.001, 70}, fillColor = {105, 210, 231}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {-9.999000000000001, 70}, fillColor = {167, 219, 216}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {-19.999, 70}, fillColor = {105, 210, 231}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {-31.917, -63.624}, fillColor = {204, 208, 224}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {-21.917, -63.624}, fillColor = {204, 208, 224}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {-11.917, -63.624}, fillColor = {204, 208, 224}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50), Rectangle(visible = true, origin = {-1.917, -63.624}, fillColor = {204, 208, 224}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, borderPattern = BorderPattern.Engraved, extent = {{-4.118, -3.624}, {4.118, 3.624}}, radius = 50)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); end Boards; @@ -274,7 +275,7 @@ end customBoard; model BlinkLed "Basic example of blinking an LED" extends Modelica.Icons.Example; replaceable OpenModelicaEmbedded.Boards.Arduino arduino(Port = "/dev/ttyACM0", ShowPinCapabilities = true, UseDTR = false) annotation(Placement(visible = true, transformation(origin = {30, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); - OpenModelicaEmbedded.Pins.DigitalOutput digitalOutput(Pin = 30) annotation(Placement(visible = true, transformation(origin = {0, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + OpenModelicaEmbedded.Pins.DigitalOutput digitalOutput(Pin = 9) annotation(Placement(visible = true, transformation(origin = {0, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica_DeviceDrivers.Blocks.OperatingSystem.SynchronizeRealtime synchronizeRealtime1 annotation( Placement(visible = true, transformation(origin = {35, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Blocks.Sources.BooleanPulse booleanPulse annotation( @@ -380,7 +381,7 @@ end BlinkLed; model SimpleONOFF "A simple On/Off controller" extends Modelica.Icons.Example; OpenModelicaEmbedded.Boards.Arduino arduino(Port = "/dev/ttyACM0") annotation(Placement(visible = true, transformation(origin = {0, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); - OpenModelicaEmbedded.Pins.AnalogInput analogInput1(MaxValue = 3.3 * 100,Pin = 23, adcResolution = 12) annotation(Placement(visible = true, transformation(origin = {30, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + OpenModelicaEmbedded.Pins.AnalogInput analogInput1(MaxValue = 3.3 * 100,Pin = 16, adcResolution = 12) annotation(Placement(visible = true, transformation(origin = {30, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Blocks.Sources.Constant Reference(k = 40) annotation(Placement(visible = true, transformation(origin = {35, -25}, extent = {{-10, -10}, {10, 10}}, rotation = -180))); Modelica.Blocks.Math.Add add1(k2 = +1, k1 = -1) annotation(Placement(visible = true, transformation(origin = {-0, -25}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Pins.DigitalOutput digitalOutput(Pin = 30) annotation(Placement(visible = true, transformation(origin = {-30, 15}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); @@ -510,10 +511,12 @@ end BlinkLed; uses(OpenModelicaEmbedded(version = "1.2"), Modelica(version = "3.2.2"), Modelica_DeviceDrivers(version = "1.5.0"))); end DCMotorWithPWM; + + model DCMotorWithPID extends Modelica.Icons.Example; Modelica_DeviceDrivers.Blocks.OperatingSystem.SynchronizeRealtime synchronizeRealtime1(priority = "High", setPriority = true) annotation( - Placement(visible = true, transformation(origin = {92, 88}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Placement(visible = true, transformation(origin = {72, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Mechanics.Rotational.Components.Inertia inertia1(J = 1, a(start = 0), phi(start = 0), w(start = 0)) annotation( Placement(visible = true, transformation(origin = {-22, -86}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Mechanics.Rotational.Components.Inertia inertia2(J = 1, a(start = 0), phi(start = 0), w(start = 0)) annotation( @@ -534,11 +537,11 @@ end BlinkLed; Placement(visible = true, transformation(origin = {-64, 2}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); OpenModelicaEmbedded.Pins.AnalogOutput analogOutput2(MaxValue = 512, MinValue = -512, Pin = 6) annotation( Placement(visible = true, transformation(origin = {-54, 58}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); - Modelica.Blocks.Sources.Sine sine1(amplitude = 512, freqHz = 0.5) annotation( - Placement(visible = true, transformation(origin = {-122, 58}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Sources.Sine sine1(amplitude = 512, freqHz = 0.5) annotation( + Placement(visible = true, transformation(origin = {-110, 58}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); equation connect(sine1.y, analogOutput2.u) annotation( - Line(points = {{-110, 58}, {-64, 58}, {-64, 58}, {-64, 58}}, color = {0, 0, 127})); + Line(points = {{-98, 58}, {-64, 58}, {-64, 58}, {-64, 58}}, color = {0, 0, 127})); connect(analogOutput2.pinConnector, customFirmata1.boardConnector) annotation( Line(points = {{-44, 58}, {-10, 58}, {-10, 4}})); connect(analogInput1.y, torque1.tau) annotation( @@ -563,6 +566,58 @@ end BlinkLed; uses(OpenModelicaEmbedded(version = "1.2"), Modelica(version = "3.2.2"), Modelica_DeviceDrivers(version = "1.5.0"))); end DCMotorWithPID; + model DCMotorWithPIDReal + extends Modelica.Icons.Example; + Modelica_DeviceDrivers.Blocks.OperatingSystem.SynchronizeRealtime synchronizeRealtime1(priority = "High", setPriority = true) annotation( + Placement(visible = true, transformation(origin = {92, 88}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Mechanics.Rotational.Components.Inertia inertia1(J = 1, a(start = 0), phi(start = 0), w(start = 0)) annotation( + Placement(visible = true, transformation(origin = {-22, -86}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Mechanics.Rotational.Components.Inertia inertia2(J = 1, a(start = 0), phi(start = 0), w(start = 0)) annotation( + Placement(visible = true, transformation(origin = {56, -86}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Mechanics.Rotational.Components.SpringDamper springDamper1(c = 20, d = 10, phi_rel0 = 0) annotation( + Placement(visible = true, transformation(origin = {16, -86}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Mechanics.Rotational.Sources.Torque torque1 annotation( + Placement(visible = true, transformation(origin = {-64, -86}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Mechanics.Rotational.Sources.ConstantTorque constantTorque1(tau_constant = 10) annotation( + Placement(visible = true, transformation(origin = {98, -86}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Modelica.Mechanics.Rotational.Sensors.SpeedSensor speedSensor1 annotation( + Placement(visible = true, transformation(origin = {88, -36}, extent = {{-10, -10}, {10, 10}}, rotation = 90))); + OpenModelicaEmbedded.Boards.CustomFirmata customFirmata1(BaudRate = 57600, Port = "/dev/ttyACM0", ShowPinCapabilities = true, UpdatePeriod = 0.02, UseDTR = true) annotation( + Placement(visible = true, transformation(origin = {-10, 4}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + OpenModelicaEmbedded.Pins.AnalogOutput analogOutput1(MaxValue = 512, MinValue = -512, Pin = 5) annotation( + Placement(visible = true, transformation(origin = {46, 2}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + OpenModelicaEmbedded.Pins.AnalogInput analogInput1(InitValue = 0, MaxValue = 512, MinValue = -512, Pin = 15) annotation( + Placement(visible = true, transformation(origin = {-64, 2}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + OpenModelicaEmbedded.Pins.AnalogInput analogInput2(MaxValue = 512, MinValue = -512, Pin = 16) annotation( + Placement(visible = true, transformation(origin = {30, 50}, extent = {{-14, -14}, {14, 14}}, rotation = 0))); + Modelica.Blocks.Interaction.Show.RealValue realValue1 annotation( + Placement(visible = true, transformation(origin = {85, 50}, extent = {{-13, -12}, {13, 12}}, rotation = 0))); + equation + connect(analogInput2.y, realValue1.numberPort) annotation( + Line(points = {{44, 50}, {70, 50}, {70, 50}, {70, 50}}, color = {0, 0, 127})); + connect(analogInput2.pinConnector, customFirmata1.boardConnector) annotation( + Line(points = {{16, 50}, {-10, 50}, {-10, 4}, {-10, 4}})); + connect(analogInput1.y, torque1.tau) annotation( + Line(points = {{-74, 2}, {-84, 2}, {-84, 2}, {-94, 2}, {-94, -86}, {-76, -86}}, color = {0, 0, 127})); + connect(analogInput1.pinConnector, customFirmata1.boardConnector) annotation( + Line(points = {{-54, 2}, {-10, 2}, {-10, 4}})); + connect(speedSensor1.w, analogOutput1.u) annotation( + Line(points = {{88, -25}, {89, -25}, {89, -23}, {88, -23}, {88, 3}, {56, 3}, {56, 1}}, color = {0, 0, 127})); + connect(analogOutput1.pinConnector, customFirmata1.boardConnector) annotation( + Line(points = {{36, 2}, {35.5, 2}, {35.5, 2}, {35, 2}, {35, 4}, {-10, 4}})); + connect(speedSensor1.flange, constantTorque1.flange) annotation( + Line(points = {{88, -46}, {88, -86}})); + connect(inertia2.flange_b, constantTorque1.flange) annotation( + Line(points = {{66, -86}, {88, -86}, {88, -86}, {88, -86}, {88, -86}, {88, -86}})); + connect(torque1.flange, inertia1.flange_a) annotation( + Line(points = {{-54, -86}, {-37, -86}, {-37, -86}, {-32, -86}, {-32, -86}, {-31, -86}, {-31, -86}, {-32, -86}})); + connect(springDamper1.flange_b, inertia2.flange_a) annotation( + Line(points = {{26, -86}, {36, -86}, {36, -86}, {46, -86}, {46, -86}, {46, -86}})); + connect(inertia1.flange_b, springDamper1.flange_a) annotation( + Line(points = {{-12, -86}, {-3, -86}, {-3, -86}, {6, -86}, {6, -86}, {6, -86}})); + annotation( + uses(OpenModelicaEmbedded(version = "1.2"), Modelica(version = "3.2.2"), Modelica_DeviceDrivers(version = "1.5.0"))); + end DCMotorWithPIDReal; annotation(Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}))); end Examples; @@ -833,7 +888,7 @@ end arduino_ex4_led_blink; model arduino_ex1_pot_threshold extends Modelica.Icons.Example; - OpenModelicaEmbedded.Pins.AnalogInput analogInput1(MaxValue = 1023, MinValue = 0, Pin = 16, adcResolution = 12) annotation( + OpenModelicaEmbedded.Pins.AnalogInput analogInput1(MaxValue = 1023, MinValue = 0, Pin = 16, adcResolution = 10) annotation( Placement(visible = true, transformation(origin = {30, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); OpenModelicaEmbedded.Pins.DigitalOutput digitalOutput1(Pin = 9) annotation( Placement(visible = true, transformation(origin = {-50, 90}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); @@ -887,6 +942,10 @@ equation annotation( uses(OpenModelicaEmbedded(version = "1.2"))); end arduino_ex1_pot_threshold; + + + + end Potentiometer; package Thermistor @@ -1597,6 +1656,7 @@ end ArduinoExamples; + class FirmataBoardObject extends ExternalObject; @@ -1792,6 +1852,6 @@ end ArduinoExamples; <p><a href=\"http://fritzing.org/\">http://fritzing.org</a></p> <p> </p> <p> </p> -<p> </p></html>", revisions = ""), version = "1.2", Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Rectangle(visible = true, fillColor = {190, 53, 19}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}, radius = 25), Polygon(visible = true, origin = {-17.857, -4.643}, fillColor = {128, 128, 128}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{42.857, 59.643}, {42.857, 64.643}, {37.857, 69.643}, {32.857, 69.643}, {-17.143, 69.643}, {-42.143, 54.643}, {-57.143, 34.643}, {-65.22199999999999, 4.643}, {-57.143, -25.357}, {-42.143, -45.357}, {-17.143, -60.357}, {32.857, -60.357}, {37.857, -60.357}, {42.857, -55.357}, {42.857, -50.357}}, smooth = Smooth.Bezier), Polygon(visible = true, origin = {-17.857, -4.643}, fillColor = {255, 255, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{42.857, 59.643}, {42.857, 64.643}, {37.857, 69.643}, {30.028, 54.643}, {-12.143, 59.643}, {-37.143, 44.643}, {-50.141, 26.339}, {-55.168, 4.643}, {-52.143, -20.357}, {-42.143, -42.453}, {-17.143, -60.357}, {32.857, -60.357}, {37.857, -60.357}, {42.857, -55.357}, {42.857, -50.357}}, smooth = Smooth.Bezier), Rectangle(visible = true, origin = {50, 27.5}, lineColor = {128, 128, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.HorizontalCylinder, extent = {{-25, -12.5}, {25, 12.5}}), Rectangle(visible = true, origin = {50, -27.5}, lineColor = {128, 128, 128}, fillColor = {255, 255, 255}, fillPattern = FillPattern.HorizontalCylinder, extent = {{-25, -12.5}, {25, 12.5}}), Polygon(visible = true, origin = {-23.077, -0.385}, fillColor = {191, 191, 191}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, points = {{38.077, 50.385}, {38.077, 55.385}, {33.077, 55.385}, {-6.923, 55.385}, {-26.923, 45.385}, {-41.923, 30.385}, {-50.213, 0.385}, {-41.923, -29.615}, {-26.923, -44.615}, {-6.923, -54.615}, {33.077, -54.615}, {38.077, -54.615}, {38.077, -49.615}}, smooth = Smooth.Bezier), Polygon(visible = true, origin = {-17.857, -4.643}, lineColor = {128, 128, 128}, fillColor = {128, 128, 128}, points = {{42.857, 59.643}, {42.857, 64.643}, {37.857, 69.643}, {32.857, 69.643}, {-17.143, 69.643}, {-42.143, 54.643}, {-57.143, 34.643}, {-65.22199999999999, 4.643}, {-57.143, -25.357}, {-42.143, -45.357}, {-17.143, -60.357}, {32.857, -60.357}, {37.857, -60.357}, {42.857, -55.357}, {42.857, -50.357}}, smooth = Smooth.Bezier)}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), +<p> </p></html>", revisions = ""), version = "1.2", Icon(coordinateSystem( initialScale = 0.1, grid = {5, 5}), graphics = {Rectangle(fillColor = {0, 170, 255}, pattern = LinePattern.None, fillPattern = FillPattern.Solid, extent = {{-100, -100}, {100, 100}}, radius = 25), Text(origin = {-47.5, 55}, extent = {{-42.5, 15}, {137.5, -80}}, textString = "OpenModelica", textStyle = {TextStyle.Bold}), Text(origin = {2.5, -15}, extent = {{-77.5, 15}, {77.5, -15}}, textString = "Embedded", textStyle = {TextStyle.Bold})}), Diagram(coordinateSystem(extent = {{-148.5, -105}, {148.5, 105}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), uses(Modelica_DeviceDrivers(version = "1.5.0"), Modelica(version = "3.2.2"))); -end OpenModelicaEmbedded; +end OpenModelicaEmbedded;
\ No newline at end of file |