Jump to content


Popular Content

Showing content with the highest reputation since 04/06/2019 in all areas

  1. 2 points
    I still do not understand why corrections have still not been made for this chip. As I needed these corrections, I had to do them myself although I am not a specialist on this subject. So I modified the necessary files to have access to all the pins of the MSP430FR5994, even those which are not cabled on the Launchpad, in order to be able to use them on my own cards. I enclose the modified files as well as the positions in the folders, to help the users facing the same problems as me. It would be desirable for the Energia team to finally address these issues and include these changes in a forthcoming release. Indeed this chip is perfect to make very good low consumption modules , and the ENERGIA concept makes it easy to develop the complementary software CORRECTED_BUGS.zip
  2. 2 points


    Certificate fixed. Thanks.
  3. 2 points
    What i2c device are you connecting? What does is do? What's the device address? (per device specs) Is it really 2? Are you using pullups? I2c requires some type of pullup, and in general, the internal resistors on the '430 devices are not an appropriate value, so external are usually used. Note: by default, i2c comms are on LP pins 9 (SCL) and 10 (SDA) not 15 &&16 - P1.6 and P1.7, Energia defaults to spi on those pins.
  4. 2 points
    My Lisp interpreter for microcontrollers, uLisp, now supports the MSP430 FR6989 LaunchPad board, with the ability to write text to the LCD display from Lisp programs: For more information see uLisp for the MSP430 FR6989 LaunchPad.
  5. 1 point
    The RAM of an MCU can’t be expanded. Go for another LaunchPad with a more capable MCU.
  6. 1 point
    Yes, this is the right file (- as the energia-1.8.10E23 did not got a update on the MSP430 tool chain - then it would be in c:\Users\USERNAME\AppData\Local\Energia15\packages\energia\hardware\msp430 - just for completeness) Yes, update both lines
  7. 1 point

    Adding new mcu to Energia

    As a form of documenting... I just added another new MCU to Energia and -in short- had to do the following to get it working: In Energia 1.8.7E21: Copy from a close family member the following files and replace the model name with the new model name in the directory-/filename and file content: \hardware\energia\msp430\variants\[existing-model]\ \hardware\tools\DSLite\common\targetdb\devices\[existing-model].xml \hardware\tools\DSLite\common\targetdb\options\[existing-model]_GNU.xml \hardware\tools\DSLite\common\targetdb\options\[existing-model]_TI.xml \hardware\tools\msp430\msp430\lib\ldscripts\[existing-model]\ \hardware\tools\msp430\msp430\include\[existing-model].h Add the new model to the following files: \hardware\energia\msp430\boards.txt \hardware\tools\msp430\msp430\include\msp430.h \hardware\tools\msp430\msp430\lib\msp430mcu.spec Of course, check for differences between the two family members (e.g. missing or added peripherals, memory sizes) and edit the copied files accordingly.
  8. 1 point
    When using the latest version of Energia the wire (I2C) has now the function setClock to set to 400k use setClock(400000UL);
  9. 1 point
    Interesting. My experience with both IAR and CCS is that they refuse to load images to a device when it's different than what the project specifies and they both clearly report it as an error.
  10. 1 point
    Rei Vilo

    RED_LED and GREEN_LED work opposite

    Yes, this is a bug, sorry a feature of the MSP-EXP430G2ET!
  11. 1 point
    The goal of this project is to utilize an MSP430 to allow existing remote-controlled outlets to by controlled over Wi-Fi. As purchased, the outlets can be controlled with a provided remote control which uses 434 MHz radio signals. By programing the MSP430 to replicate the signals from this remote and hosting a web page with controls on the MSP430, the outlets can be able to be controlled from anywhere on the same Wi-Fi network. The completed project provides a web page that can both control each of three outlets individually or all three at once. This is done using an MSP430 as a controller with a 434MHz transmitter sending commands to the outlets, and an ESP 8266 Wi-Fi module connecting to the network. A schematic of the completed project is shown in Fig. 1, and a photo of the completed project is shown in Fig. 2. With this set up the outlets can be reliably controlled from anywhere on the same Wi-Fi network. The components required for this project, along with the equipment necessary are listed below. All the components can be purchased for less than $30. I was able to write an interface to control the outlets, as well as serve a webpage to control the outlets. This was the final project for my Embedded Systems class at John Brown University. more details are avalible in the attached file. Parts list: · TI MSP430G2553 Launchpad · 434 MHz RF transmitter https://www.sparkfun.com/products/10534 · ESP8266 wifi module · Syantek Remote Controlled Outlets https://www.amazon.com/Syantek-Electrical-Household-Appliances-Expandable/dp/B07JF93XB5 · Breadboard · Jumper cables · USB power supply Equipment · 434 MHz RF receiver https://www.sparkfun.com/products/10532 · Digilent Analog Discovery Module · Code Composer Studio · Serial to USB converter Light_Switch_Final_Report.docx
  12. 1 point

    Interrupts for TM4C123GXL

    I posted a library a while ago which could be of use. It can be found here: https://github.com/energia-libraries/RotaryEncoder
  13. 1 point


    A few updates and notes: The forum is finally able to connect to the license server. It failed due to an older version of curl, which caused alot of spam posts. PHP updated to the latest version Forums upped to 4.4.7 Any issues, please note them here. I'll try to sort things out. Thank you!
  14. 1 point
    Hi Geometrikal, Hi TL The portage works perfectly, it is only necessary to put the good chip select for the Launchpad as well as to specify the good bus SPI in the file Jaffl.cpp in the routine SPI_INIT. For the applications which I use I tested at the same time the competition between the SPI bus (0) which manages the SD card and the SPI bus (1) which manages another device. I enclose all the necessary sources to test on a Launchpad MSP430FR5994. For my work I use Visual Studio 2019 with the Visual Micro plugin. I can compile for Arduino (Arduino,ESP8266,ESP32,ST) and Energia families in an efficient way. Jaffs_MSP5994.zip
  15. 1 point
    (I started this [Energia Library] topic and copied my spiE library over to make it easier to find) I wanted to improve the compatibility of the SPI.h lm4f library to include functions of arduino user contributed SPI.h libraries. I found SPI2.h here: http://forum.stellar...two-spi-modules. This library added multi-module features but removed the 123 & 1294 compatibility. I have merged SPI2 and the core SPI libs into spiE.h and added several more function variations. spiE.h best features are: 1. Array transfer up to 255 bytes. This is 5x faster than single byte transfer. 2. SPI2's pinMode() and digitalWrire() functions are replaced with faster macros. 3. Support for __TM4C129XNCZAD__, __TM4C1294NCPDT__, BLIZZARD_RB1 (LM4F) boards 4. Up to 4 instances can be defined: SPI0, SPI1, SPI3, & SPI2 is instantiated by default as SPI for arduino code compatibility. 5. Multiple SlaveSelect pins can be used fir multiple devices on one data line. defaultSS, default +SS2, or SS1 + SS2, etc. I have tested this on the 129. If you have a need for it and can try it on the other boards before I upload it to github, be my guest. spiE.zip
  16. 1 point
    Rei Vilo

    Best way change I2C freq to 400kHz

    Please refer to Wire.cpp#L121-L123 I2C_Params_init(&params); params.transferMode = I2C_MODE_BLOCKING; params.bitRate = I2C_400kHz;
  17. 1 point
    HI ! No MQTT with AT commands on ESP6266 IMHO !! (among the several AT firmwares I know) You can use Arduino IDE (+ ESP8266 core) to flash your ESP-01 with your own application receiving data through UART and publishing data to an MQTT broker (use pubsub library) (WEMOS D1 mini is a good alternative to ESP-01 with it's good 3V3 regulator, some passive components, USB interface for easy developping...)
  18. 1 point
    Rei Vilo

    MSP low power configuration

    Please refer to Ultra-Low Power with MSP430 at https://embeddedcomputing.weebly.com/ultra-low-power-with-msp430.html Ultra-Low Power with Energia MT and Galaxia at https://embeddedcomputing.weebly.com/ultra-low-power-with-energia-mt-and-galaxia.html The MSP432P401R LaunchPad programmer features EnergyTrace to be used with Code Composer Studio. Ultra-Low Power with EnergyTrace at https://embeddedcomputing.weebly.com/ultra-low-power-with-energytrace.html
  19. 1 point

    CC1312R1 Energia

    Not yet but will be soon.
  20. 1 point
    Rei Vilo

    CC1312R1 Energia

    Not yet, stay tuned!
  21. 1 point

    MSP430G2 no communication

    To solve the UART issue go to the pins_energia.h file for the selected device MSP-EXP430G2452LP and try to update / modify this lines: static const uint8_t DEBUG_UARTRXD = 4; /* Receive Data (RXD) at P1.2 */ static const uint8_t DEBUG_UARTTXD = 3; /* Transmit Data (TXD) at P1.1 */ This seems to be wrong in the current version but i have no idea why this worked before as i could not find an update where this has been changed. To solve the issue with I2C you need to select the other I2C interface with setModule(0); The default mapping of the I2C interface to the pins 8 and 9 change a while ago but with the setModule you still can select the other I2C interface if available.
  22. 1 point

    MSP430G2 no communication

    You've described the problem, but supplied no information to allow remote diagnosis. Without a schematic and related code, there's really no way to help, aside from the most general suggestions regarding jumpers, pins and I2C pullup resistors, all of which you've likely read (and hopefully applied). Finally, you mention migrating an existing project; did you have that working, and if so, under what version of Energia? Re: UART - there may be no hardware UART on your chip. "If your Launchpad is version 1.4 or earlier, the chips that it shipped with have no hardware UART and thus, no hardware configuration is necessary, but you must use the SoftwareSerial library included in Energia to communicate over the serial port." You indicate you have an MSP430G2452, according to SLAU318G, there is only USI availble on that chip, the UART is on the G2553's USCI impementation.
  23. 1 point

    Online programmer for MSP430!

    You edit C-code within your web browser without having to install an IDE such as IAR or CCS on your computer. The files are compiled on our server and you download them from there. This online compiler is based on the open source MSPGCC and is available today as a BETA.
  24. 1 point

    I2C- MSP-EXP430G2ET

    @Anshikajain Sorry, I've been offline for a couple of days. Not really sure what your question was, but FWIW, I rarely use Energia. That said, when I2C fails in Energia, it's almost always a configuration problem. My suggestion with the video was focused on how they configured the '430 jumpers. The G25 devices were significantly different from the later versions, and many have tripped over jumpers incorrectly configured. In your photo it appears you have the jumper P1.6 placed for the LED, and that was the very first comment in the video - the device will not work in I2C mode if that jumper is placed (at least on the older boards). Looking at the docs, pins P2.1 and P2.2 are designated as SCL and SDA (sw), which I presume means software, not hardware I2C? It's difficult to see in your photo, but it looks like you're using P1.6 and P1.7. So, the video's comments, and this from Energia docs: " When using I2C When using the Hardware I2C (Wire library) with SCL on P1.6 and SDA on P1.7 on the MSP-EXP430G2 you should remove the P1.6 jumper (GREEN LED) so that the LED doesn’t interfere with the I2C SCL signal... " Energia reference I don't know if I'm able to help much further. Please check your jumpers!
  25. 1 point
    Some different styles of ceramic capacitors for use in electronic equipment. Multilayer ceramic chip capacitor (MLCC) Ceramic disc capacitor (single layer) Feedthrough ceramic capacitor. High voltage ceramic power rcapacitor.
  26. 1 point

    Blink example too slow

    this issue got already fixed a while ago - unfortunately the fix did not get merged into the master branch. Just did the update there so it will go into the next release. Meanwhile you can fix this locally with patching the wiring.c file. In the function InitClock update the first lines to: void initClocks(void) { #ifdef __MSP430_HAS_BC2__ #if (defined(CAL_BC1_16MHZ) || defined(CALDCO_16MHZ_)) && F_CPU >= 16000000L BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; #elif (defined(CAL_BC1_12MHZ) || defined(CALDCO_12MHZ_)) && (F_CPU >= 12000000L) BCSCTL1 = CALBC1_12MHZ; DCOCTL = CALDCO_12MHZ; #elif (defined(CAL_BC1_8MHZ) || defined(CALDCO_8MHZ_)) && (F_CPU >= 8000000L) BCSCTL1 = CALBC1_8MHZ; DCOCTL = CALDCO_8MHZ; #elif (defined(CAL_BC1_1MHZ) || defined(CALDCO_1MHZ_)) && (F_CPU >= 1000000L) BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; #else #warning No Suitable Frequency found! #endif #endif
  27. 1 point
    Hi, I wrote an article (in Portuguese) about how to use the SD16 ADC of MSP43F2013, and to show one practical application I transformed the MSP430F2013 in an I2C 16-bit ADC, similar to ADS1115. In the example, I read the data using one Arduino Nano. Comparing the conversion of SD16 and ADS1115: More details about the project can be found in my Github: https://github.com/agaelema/msp430f20x3_as_i2c_16bit_adc The project is open to further improvements/optimizations and functions.
  28. 1 point

    [POTM] dAISy - A Simple AIS Receiver

    Hi Varnak, The dAISy software does change the channel every so often. The code for switching between the channels start at line 329 in packet_handler.c https://github.com/astuder/dAISy/blob/master/packet_handler.c#L329 The receiver will switch to the other channel when the state is PH_RESET, which is the case after an error, successful message, or when there is no start of message within PH_SYNC_TIMEOUT (defined in line 27) clock ticks (one tick being 1/9600 second). Statistically, it will miss at least 50% of the message as it can only listen on one channel at a time. Regards, Adrian
  29. 1 point

    [POTM] dAISy - A Simple AIS Receiver

    Hi Adrian! I was in St. Petersburg, recorded the AIS broadcast and was surprised when I played it on the second frequency 162.025 at home ... it works too!))) But WDS is set to 161.975. Do you programmatically switch channels by RSSI level and after what time? If you can tell me where in the program it is. I'm not a programmer at all. Here's a video of how your dAISy looks at me)) 20190428_184322.mp4
  30. 1 point
    p.s. you should use the first Sketch you posted. Also make sure that the master is setup to talk to the right address you specify in the Wire.begin(addr) call.
  31. 1 point
    There is a bug for slave mode which has already been fixed in the git repo. You can work-around it with the following. If you have the latest Energia release installed (1.8.7E21), then edit the file: Linux: <Energia directory>hardware/energia/msp430/libraries/Wire/utility/twi.c Windows: <Energia directory>hardware\energia\msp430\libraries\Wire\utility\twi.c macOS: <Energia.app directory>/Contents/Java/hardware/energia/msp430/libraries/Wire/utility/twi.c Got to line 1183 and replace: 1183 } else if (twi_state == TWI_MRX) { // Master receive mode 1184 // copy data to output register 1185 UCBzTXBUF = twi_txBuffer[twi_txBufferIndex++]; by this: 1183 } else if (twi_state == TWI_STX) { // Slave transmit mode 1184 // copy data to output register 1185 UCBzTXBUF = twi_txBuffer[twi_txBufferIndex++];
  32. 1 point

    [POTM] dAISy - A Simple AIS Receiver

    FYI: dAISy works in Direct RX mode. Unfortunately, the built-in packet handler of the radio IC does not work with AIS.
  33. 1 point

    [POTM] dAISy - A Simple AIS Receiver

    Hi Varnak, I just pushed a configuration file for WDS 3.2.11 that I had laying around. I haven't tested it, so not sure if it works as is. https://github.com/astuder/dAISy/blob/master/WDS3211_si4362_revb1_direct_rx.xml Best Regards, Adrian
  34. 1 point
    So I spent some time with the latest energia 1.8.7E21. It is still using msp430-gcc. That project I linked in the previous post won't work because that code is using the newer msp430-elf-gcc. I did put together an example of using msp430-gcc style code and the blink project above that compiles and create asm only project .. well almost main has to jump to our asm code so there are a couple of instructions to get there. Three files are needed: blink_with_msp430-gcc_asm.ino /* blink_with_msp430-gcc_asm.ino */ /* * we aren't going to use the .ino file */ main.cpp // We override the main function from Energia // and just jump to our __reset_vector__ routine // in blink.S int main() { asm("jmp _reset_vector__"); } blink.S ;------------------------------------------------------------------------------- ; blinkasm.S - gcc compatible interrupt driven led blinker in msp430 asm ; ; Version 1.0 - 10/22/2011 rick@kimballsoftware.com ; Version 1.01 - 7/22/2014 rick@kimballsoftware.com modified for msp430-elf-gcc ; Version 1.02 - 11/02/2014 rick@kimballsoftware.com more changes for msp430-elf-gcc ; $ msp430-elf-gcc blinkasm.S -D_GNU_ASSEMBLER_ -Wall -Os -g \ ; -fdata-sections -ffunction-sections -mmcu=msp430g2553 -T \ ; -T msp430g2553.ld -I/tmp/a/include -L /tmp/a/include/ -nostdlib ; Version 1.03 - 03/16/2019 rick@kimballsoftware.com made compatible with energia ; ;------------------------------------------------------------------------------- .file "blinkasm.S" #include <msp430.h> ;------------------------------------------------------------------------------- ;;; ---- gcc doesn't know about PC,SP,SR,CG1,CG2 ---- #define PC r0 #define SP r1 #define SR r2 ;------------------------------------------------------------------------------- ;;; ---- CONSTANTS ---- //#define TEST_IRQ_OVERHEAD #ifndef TEST_IRQ_OVERHEAD #define _50USEC (50-1) /* @1MHz MCLK results in 50uSec/interrupt */ #define _500MSEC 10000 /* @1MHz MCLK results in 500ms/LED toggle */ #else ;; This test illustrates the minimum CCR0 value that can be used ;; 22 cycles is based on the interrupt overhead #define _50USEC 22 /* @1MHz MCLK results in 23uSec/interrupt */ #define _500MSEC 1 /* @1MHz MCLK results in 23uSec/LED toggle */ #endif #define _LED_PIN BIT6 /* PORT1 pin, Launchpad has BIT0=Red and BIT6=Green */ ;------------------------------------------------------------------------------- ;;; ---- Registers used as globals ---- #define LED_PIN r4 #define TIMER_CYCLES r5 #define INTERVAL_CNT r6 #define CNT r7 ;; or you could use some ram variables .lcomm tcycles,2 ; example use of local bss data variable .lcomm cnt,2 ; example use of local bss data variable ;------------------------------------------------------------------------------- .section .text,"ax",@progbits ;------------------------------------------------------------------------------- .global _reset_vector__ ; it is important to name it "_reset_vector__" ; we prevent the C runtime start code from getting ; linked by using this name _reset_vector__: ;; disable watchdog and set stack to highest RAM addr mov.w #WDTPW|WDTHOLD,&WDTCTL mov.w #__stack,SP ; gcc ldscripts compute __stack based on mmcu ;; initialize clock,gpio,timer init: ;; configure DCO to precalibrated 1MHz clr.b &DCOCTL mov.b &CALBC1_1MHZ,&BCSCTL1 mov.b &CALDCO_1MHZ,&DCOCTL ;; initialize global register values mov.w #_LED_PIN,LED_PIN ; load constant into register constant mov.w #_50USEC,TIMER_CYCLES ; load constant into register constant mov.w #_500MSEC,INTERVAL_CNT ; load constant into register constant mov.w INTERVAL_CNT,CNT ; initialize register based counter ;; initialize GPIO bic.b LED_PIN,&P1OUT ; LED turned off to start bis.b LED_PIN,&P1DIR ; Configure P1.0 as output pin ;; initialize TimerA0 mov.w #CCIE,&TA0CCTL0 ; Enable TA0CCR0 interrupt mov.w TIMER_CYCLES,&TA0CCR0 ; Set TIMER_CYCLES cycles mov.w #TASSEL_2|MC_2,&TACTL ; SMCLK, Continuous Up Mode ;; enable interrupts and loop forever ;; real work done in the CCR0 interrupt nop eint loop: ;; Note: could sleep here instead jmp loop ; cycles:2 ;------------------------------------------------------------------------------- ; TIMER0_A3_ISR - Timer0_A3 CCR0 interrupt handler for vector 0xfff2 ;------------------------------------------------------------------------------- .global __isr_9 ; to insert an interrupt vector into the vector ; table from assembly, we have to use a specific ; naming convention we must call this function ; "__isr_9" this forces it into the 9th vector ; slot counting from 0 starting memory address ; 0xffe0. It is 9 because each vector is ; 2 bytes so we end up in slot 0xfff2 ; all this is because of the way msp430-gcc ; works with interrupts ; .vectors in the msp430g2553/memory.x starts ; @ 0xffe0 ; there are numbered isr_0 ... isr_14 even though ; there are 16 vectors. isr_15 is actually called ; _reset_vector__ you can see how we use it in this ; code. ; see the file: ; http://www.ti.com/lit/ds/symlink/msp430g2553.pdf ; look at the "Interrupt Vector Table" page 11 __isr_9: ;; before we even start running the mcu does a push PC, and a push SR cycles:6 dec.w CNT ; have we looped INTERVAL_CNT times? cycles:1 jnz 1f ; exit if we haven't reached 0 cycles:2 ;; toggle led pin after (INTERVAL * TIMER_CYCLES) has occured xor.b LED_PIN,&P1OUT ; cycles:4 mov.w INTERVAL_CNT,CNT ; reinitialize interval counter cycles:1 1: add.w TIMER_CYCLES,&TA0CCR0 ; set new CCR0 and go again cycles:4 reti ; cycles:5 ; vim: ts=8 sw=8 expandtab: Put those in a new Energia sketch compile it for an msp430g2553 and it should produce output that looks like this: blink_with_msp430-gcc_asm.ino.elf: file format elf32-msp430 Disassembly of section .text: 0000c000 <main>: c000: 03 3c jmp $+8 ;abs 0xc008 c002: 0f 43 clr r15 0000c004 <__ctors_end>: c004: 30 40 5e c0 br #0xc05e 0000c008 <_reset_vector__>: c008: b2 40 80 5a mov #23168, &0x0120 ;#0x5a80 c00c: 20 01 c00e: 31 40 00 04 mov #1024, r1 ;#0x0400 0000c012 <init>: c012: c2 43 56 00 mov.b #0, &0x0056 ;r3 As==00 c016: d2 42 ff 10 mov.b &0x10ff,&0x0057 c01a: 57 00 c01c: d2 42 fe 10 mov.b &0x10fe,&0x0056 c020: 56 00 c022: 34 40 40 00 mov #64, r4 ;#0x0040 c026: 35 40 31 00 mov #49, r5 ;#0x0031 c02a: 36 40 10 27 mov #10000, r6 ;#0x2710 c02e: 07 46 mov r6, r7 c030: c2 c4 21 00 bic.b r4, &0x0021 c034: c2 d4 22 00 bis.b r4, &0x0022 c038: b2 40 10 00 mov #16, &0x0162 ;#0x0010 c03c: 62 01 c03e: 82 45 72 01 mov r5, &0x0172 c042: b2 40 20 02 mov #544, &0x0160 ;#0x0220 c046: 60 01 c048: 03 43 nop c04a: 32 d2 eint 0000c04c <loop>: c04c: ff 3f jmp $+0 ;abs 0xc04c 0000c04e <__isr_9>: c04e: 17 83 dec r7 c050: 03 20 jnz $+8 ;abs 0xc058 c052: c2 e4 21 00 xor.b r4, &0x0021 c056: 07 46 mov r6, r7 c058: 82 55 72 01 add r5, &0x0172 c05c: 00 13 reti 0000c05e <_unexpected_>: c05e: 00 13 reti Disassembly of section .vectors: 0000ffe0 <__ivtbl_16>: ffe0: 04 c0 04 c0 04 c0 04 c0 04 c0 04 c0 04 c0 04 c0 ................ fff0: 04 c0 4e c0 04 c0 04 c0 04 c0 04 c0 04 c0 08 c0 ..N............. To get your SD Card Bootloader running in Energia you would have to replace the blink.S with SDBSL-G2553.S and change your coding style to make msp430-gcc happy. You would also have to replicate all the code that the normal C runtime code does to create an environment for a C++ application. Basically you have to setup the .data section (copying the initial values from flash to ram), initialize the .bss section all to zero, loop through all the global c++ constructors, then call the users main function. blink_with_msp430_asm.zip
  35. 1 point
    I'm going to assume you want to actually learn, and not just be handed "the answer." Take a look at this on stackoverflow, it should help you figure out a solution your problem.
  36. 1 point

    How do you like this forum platform?

    Looks like a fair bit of activity with members posting comments and blogs. How do you guys like it? Is it easier to navigate? Responsive? Let me know. Thanks!
  37. 1 point
    Rei Vilo

    [Energia Library] I

    Please find a library for the I INA219_Distribution206.zip
  38. 1 point
    I find Energia suitable for many most of my projects. Much of the time direct register access is not needed. But if you keep at it long enough and stretch the boundaries of what others have done and posted, then expect to encounter the limitations of Energia / Arduino or at least the need to understand what is happening at the register level. It may be in terms of the software, the libraries, slow execution, lack of access to features, or that your desired microcontroller does not have an Energia port. If you learn to directly access registers then all peripherals and capabilities are available. If you want to understand and port other libraries that use direct register access then clearly a deeper understanding is needed as well. As long as you don't introduce a conflict then direct register programming and Energia work together fine and it is not one or the other. I would start with CCS and the workshop that L.R.A suggests if using the G2553. There are also tutorials on using CCS. I find the debugger in CCS invaluable even when using Energia. Gaining familiarity with the datasheets, the family user guides, and header files was the most difficult part for me as I have no microcontroller or C/C++ background - but they are key. My approach was to become proficient in Energia and then add the more traditional approach as I went along. I even find that myself writing everything in CCS without Energia from time to time now
  39. 1 point
    Hi @@cwpotter It sounds like an interesting project. That boosterpack looks pretty neat. I don't have any experience with the 430BOOST-ADS1118 but took a quick look at this and here are some things that you should look into... The library you link to seems to have been written for the C2000 - so you would need to port it to the CC3200. You definitely don't want to download the entire thing if it is written for the C2000 - probably just the .ino, .cpp and .h files. Error messages will tell you where to proceed from there. Do they say something is missing? Then look for it in the repository. Libraries are installed in Energia the same way they are installed for Arduino with the exception of location - see for example this: https://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use/arduino-libraries?view=all Note that you can find the correct location for user libraries by opening File ==> Preferences in Energia which shows sketch locations. At this location will be a folder called libraries. Install libraries there. To be honest, I would probably use an earlier version of Energia Sometimes it is easier to start over and use existing code as a go-by. You have 3 sources apparently the C2000 sketch, the firmware for the G2553 that comes with the backpack (probably not Energia), and the code at element14 - none of it for the CC3200 although the C2000 appears to have been written for Energia. How much sense does the code in these sources make to you? If not much, then you are going to do some homework to get this going with anything other than the RPi. Provided of course the RPi code already does what you want pretty much.
  40. 1 point

    3phase variable speed motor drive

    Hi there Here is my 3phase variable speed motor drive booster pack This has been in my mind for some years, but I always thought that a 3phase variable speed inverter drive is beyond my humble hobbyist scope. Too complicated for my old 8-bit mind ;-) Such a inverter contains: 6 high voltage FETs or IGBTs, 6 gatedrives, at least one DSP, a protection concept, all the software to create the 3-phase PWM, dead time control..... Still that was for quite some time on my long-term "to do" list, with no chance to actually materialize it, not enough time, too many other things to do. When playing around with the PWM module of the TM4C123 I found out that creating a 3phase PWM signal with this module is actually pretty easy. Combined that with an integrated Power Module such as the FSB50550 (Fairchild). So here it is: a booster pack for the Tiva Launchpad which drives big-ass 3phase motors. The booster pack contains the following: - the FSB50550 power module (6 FETs 500V 1.4Ohm, Gatedrivers, Bootstrap diodes, Temp sensor) - snubber capacitor Power supply: everything is powered from one DC source, 20V or (much) more. - 15V switchmode power supply from the high voltage side, built around a LNK304, for the FSB50550 - 3.3V switchmode power supply from the 15V to power the Launchpad, built around a LT1376 Measurement: - Passive voltage dividier to measure the input voltage - Sense resistor and LM339 comparator for overcurrent detection Display: - Nokia 5110 display Potentiometer for motor speed and direction The software is based on Energia using Tiva Ware function calls for all the PWM stuff. It is still work in progress, very basic and at the moment consists of: - calculate the sinwave lookup table at startup - PWM initialisation (PWM set to 15625 Hz, deadtime 1us, sync on) - a timer interrupt run every 10uSecs, do update the 3 PWD duty cycles - ADC measurement of temperature, voltage, current (moving average) - fault interrupt The main program is very short, the display is updated twice a second and the modulation factor is calculated out of the potentiometer speed setting and the applied DC voltage. Sudden changes in motor frequency are limited in the software, to prevent the motor to feed back energy and cause overvoltage. The motor on the picture is a 1/2hp, 900rpm, 6-pole motor, 12 kg of Italian steel and copper, probably 50 years old. For playing around, I apply about 50% of rated volt/hz, so current and maximum torque is reduced. Currently I use my dual 35V 4A lab supply, series connected, as a power source. here is the code: //simple 3phase frequency converter //27.9.2014 by maelli #define dots 192 //dots per halfhave, must be divisible with 3 #define period 5120 //80Mhz/5120 = 15625 switching frequency #define dt 80 //deadtime 80Mhz / 80 = 1uS #define PART_TM4C123GH6PM #include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_sysctl.h" #include "inc/hw_types.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "driverlib/pwm.h" #include "LCD_5110.h" #include "inc/tm4c123gh6pm.h" LCD_5110 myScreen (33,37,36,35,34,38,17); char celsius[3]={0x7f,'C',0x00}; uint16_t a,dire=0,modu,tensec; uint32_t timecount,sintable[dots]; volatile int32_t irqcount,timeset; volatile uint32_t temperature, voltage, current, poti; void setup(){ myScreen.begin(); myScreen.setBacklight(0); myScreen.text(0, 0, "3ph Converter"); for(int i=0;i<dots;i++) sintable[i]=sinf((i*3.14159)/dots)*(period/2-dt); unsigned long ulPeriod; unsigned int Hz = 10000; // interupt frequency in Hz ulPeriod = (SysCtlClockGet() / Hz); initTimer(); charge_gdu(); ROM_TimerLoadSet(TIMER0_BASE, TIMER_A,ulPeriod -1); initPWM(); } void loop(){ if (irqcount>499) { //20x per sec irqcount-=500; int32_t fsoll=732*(poti-16384); int32_t diff=fsoll-timeset; if (diff>0){ if (diff>150000) timeset+=150000; else timeset=fsoll; } else { if (diff<-150000) timeset-=150000; else timeset=fsoll; } modu=abs(timeset)/voltage/16; if (modu<(32000/voltage)) modu=32000/voltage; if (modu>256) modu=256; tensec++; if (tensec==10) { //2x per sec we display something tensec=0; myScreen.text(0, 1, mkstrg((temperature-325)/24,2)); myScreen.text(2, 1, celsius); myScreen.text(5, 1, mkstrg((voltage)/23,3)); myScreen.text(8, 1, "Volt"); myScreen.text(0, 2, mkstrg(abs(timeset)/322122,2)); myScreen.text(2, 2, "."); myScreen.text(3, 2, mkstrg(abs((timeset/32212)%10),1)); myScreen.text(4, 2, "Hz"); myScreen.text(7, 2, mkstrg(current,4)); myScreen.text(11, 2, "mA"); if (timeset<0) myScreen.text(0, 3, "links "); else myScreen.text(0, 3, "rechts"); } } } String mkstrg(int d,uint8_t l){ char display[l+1]; int q=1; display[l]=0; for (uint8_t a=l;a;a--){ display[a-1]=0x30+(d%(q*10))/q; q*=10; } return display; } void initTimer(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); // 32 bits Timer TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0Isr); // Registering isr ROM_TimerEnable(TIMER0_BASE, TIMER_A); ROM_IntEnable(INT_TIMER0A); ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } void charge_gdu(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 ); ROM_GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_0,GPIO_STRENGTH_4MA,GPIO_PIN_TYPE_STD); GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7); //alle 3 oberen ausschalten HWREG(GPIO_PORTA_BASE + (GPIO_PIN_7 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_1 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_3 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0); //auch die 2 letzten aus HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6); //den ersten unteren ein HWREG(GPIO_PORTA_BASE + (GPIO_PIN_6 << 2)) = GPIO_PIN_6; delay(1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = GPIO_PIN_0; delay(1); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = GPIO_PIN_2; delay(1); } void initPWM(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); //The Tiva Launchpad has two PWM modules (0 and 1). We are using 1 ROM_GPIOPinConfigure(GPIO_PD0_M1PWM0); ROM_GPIOPinConfigure(GPIO_PD1_M1PWM1); ROM_GPIOPinConfigure(GPIO_PA6_M1PWM2); ROM_GPIOPinConfigure(GPIO_PA7_M1PWM3); ROM_GPIOPinConfigure(GPIO_PF2_M1PWM6); ROM_GPIOPinConfigure(GPIO_PF3_M1PWM7); ROM_GPIOPinConfigure(GPIO_PF4_M1FAULT0); ROM_GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 ); ROM_GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7 ); ROM_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4); PWM1_0_FLTSEN_R =3; //PWM fault inverted see page 1169 GPIO_PORTF_PUR_R=0x10; //weak pullup for Pin 4 ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, period); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_0, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_1, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_3, dt,dt); ROM_PWMSyncTimeBase(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_0); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_1); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_3); delay(1); PWMFaultIntRegister(PWM1_BASE, oh_shit); ROM_PWMIntEnable(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, true); } void Timer0Isr(void) { //10000x per second ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // Clear the timer interrupt irqcount++; timecount+=timeset; // 1 Hz is 192x256*256*256/10000=322122.5 if (timecount> 0xEFFFFFFF) timecount+=0xC0000000; if (timecount> 0xBFFFFFFF) timecount-=0xC0000000;; a=timecount>>16; a=a/(16384/(dots/3*2)); //a immer kleiner 2*dots: C000 *dots/3*2/ 4000= 12 *dots/3*2/4= 2*dots if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2-sintable[a-dots]*modu/256); ROM_PWMSyncUpdate(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); switch(irqcount%10){ case 0: temperature=(temperature*127+analogRead(26))/128; break; case 1: voltage=(voltage*31+analogRead(27)*3)/32; break; case 2: current=(current*127+analogRead(25)*8)/128; break; case 3: poti=(poti*127+analogRead(28)*8)/128; break; } } void oh_shit(void) { //in case of severe overcurrent we shut down! ROM_PWMFaultIntClearExt(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, false); }
  41. 1 point
    Attached is my latest version of the Real Time Clock library, adapted from xv4y's original library. Some significant changes in this version are: Now works with both the MSP430G2553 and the MSP430G2452 processors (with some limitations on the 2452). The library may work on other processors, but I don't have any to test with. Rewrite of the logic used to detect the number of days in a month and leap year detection so that it uses considerably less RAM. Option to use the built-in VLO clock. The VLO is much less accurate than the crystal - about the best that can be achieved is accuracy to within a few minutes per day. The advantage of the VLO is that it frees up 2 IO pins, and can be used if you can't solder the tiny crystal to the launchpad. If you don't need a very accurate clock, or have a means of external synchronisation, the VLO may be sufficient for your needs. The #define's that configure the settings of the timer have been moved to a separate RTCconfig.h file, so they are easier to edit without having to edit the main header file. Documentation has been moved from the header file into a separate .txt file. Some example files have been included in the library. Known Limitations: Because the MSP430G2452 only has one timer, the RTC library cannot be used in conjunction with other functions that also require the timer. This includes Serial, AnalogWrite, Tone, and possibly some others. Because the MSP430G2452 doesn't have hardware serial, this means that the RTC library and Serial are completely incompatible. RTCplus.zip
  42. 1 point
    I'm receiving many mails about the libraries I've developed and I'm sharing. The libraries are plug-and-play as I'm using them in my projects. However, they are designed for a specific configuration. For example, a SD-card library requires a minimum of 512 bytes of RAM as this is the size of a sector. So it won't work on the MSP430G2553. With so many LaunchPads, BoosterPacks and components possible combinations, the one-fits-all approach is just impossible. It would end with lengthy and hard to read code with many pre-processing statements. For example, changing the pins names for the pins numbers improves the portability of the library across the LaunchPad range of boards. Even if the library works out of the box, they are provided as examples and require some work from the user. This is the best way for learning. The user should read and understand them, and then customise them so they can match his/her exact needs. With new hardware and software releases coming out, a library may suffer from obsolescence. It used to work with a prior version but no longer works with the new one. For example, each new release of Energia or CCS adds new features and some times modifies others in order to ensure compatibility across the whole range. Finally, feel free to improve and share back the libraries with the community This is a cross-post with Stellarisiti.
  43. 1 point

    analogWrite() precision question

    @@altineller not really, no. It's something of a hidden function. You have to include wiring_analog.c (#include <wiring_analog.c>) to kick things off. That includes the PWMWrite function. Then you can call it thusly: PWMWrite(PIN,numberOfSteps,dutyCycle,frequency); For example: PWMWrite(PD_1,500,250,6000); Would start PWM on pin PD_1, 500 steps from 0 to 100%, 50% duty cycle (500 / 2 = 250), 6000Hz frequency. It's worth noting that the function call does glitch when you call it on a pin already putting PWM out. It's not enough to hear driving a speaker, but it could cause you issues if you're calling it a lot. There's a thread around here somewhere on that subject. The frequency cap is very high, if I recall correctly I'd tested it to work >1MHz. I could be thinking about a different MCU, I've tested sort of a lot of them.
  44. 1 point
    Hi All, I found another one (after the first, prepared by Rei Vilo) interesting library for TI INA219 IC by Jarzebski This library working on stellaris without any modyfication. links: TI page about INA219 Rei Vilo library at 43oh and Embedded Computing Jarzebski github - other interesting stuff for GY80 (L3G4200D, HMC5883L, BMP085, ADXL345) Jarzebski blog (PL)
  45. 1 point
    I've spent some time recently experimenting with the Tiva timer PWM mode (not the PWM module). I have modified the wiring_analog.c such that duty cycle changes using PWMWrite() are now glitch free. Hence it is suitable for driving servos and other timing critical sources with frequent duty cycle updates. No interrupts are required. The changes are: - bypassing the timer disable/reset if it is already initialized to the PWM mode; - setting both MRSU and ILD bits in the Mode register such that both frequency and match register update are postponed to the next timer period; - the intermediate result of the duty cycle computation is increased so that large analog_res values do not cause overflow (useful for setting the duty cycle in microseconds for the servo) I tried to do a "minimally invasive" code modification to avoid compatibility issues. If the module interface change is acceptable then things can be done a bit cleaner/faster. Since I've already spend time learning the Tiva timer internals I can do further tweaks to the code if there is a community consensus on the optimal PWM interface (as a superset of Arduino). Try the code and see if you find any issues with it. If it does not cause any compatibility problems perhaps someone can help me integrate it into the next energia release. wiring_analog.c
  46. 1 point
    Ok, I found a partial workaround within a baseline Energia framework. The idea is to re-sync analogWrite() to the pwm signal iself . This works OK up to around 580Hz PWM frequency (good enough for my brushed motor PID controller project). For highly dynamic PWM (like audio) I have to dig deeper... int pwm; int dir; void setup() { //attach the PWM update interrupt handler to the PWM pin itself //*must* use the *rising* edge (falling edge messes up PWM) //on my Tiva-C Launchpad this works up to ~580Hz PWM frequency attachInterrupt(RED_LED, handler, RISING); //prime the pwm pin interrupts pwm = 1, dir = 1; analogWrite (RED_LED, pwm); } void loop() { pwm += dir; //pwm value should be constrained between 1 and 245, otherwise interrupts stop if (pwm == 254 || pwm == 1) dir = -dir; delayMicroseconds(2733); //some random value } //handler without the pwm value change detection logic void handler() { analogWrite (RED_LED, pwm); } /* //handler with the pwm value change detection logic void handler() { static int p_pwm = -1; if (p_pwm != pwm) { analogWrite (RED_LED, pwm); p_pwm = pwm; } } */
  47. 1 point
    Ok: #include <wiring_private.h> void setup() { // put your setup code here, to run once: pinMode(PF_0, OUTPUT); } void loop() { // put your main code here, to run repeatedly: PWMWrite(PF_0, 256, 200, 15000); while(1) delay(100); } Saleae Logic16 shows a waveform with width=52.1uS, period=66.68uS, frequency = 14.997KHz. Pretty close. 52.1/66.68 = 0.781343, 256*0.781343 = 200.02 so that looks right. Running this: #include <wiring_private.h> void setup() { // put your setup code here, to run once: pinMode(PF_0, OUTPUT); } void loop() { // put your main code here, to run repeatedly: PWMWrite(PF_0, 256, 200, 15000); delay(100); } ...produces ALMOST the same thing, but every 100ms there's a single pulse whose width is 101.65uS instead of the typical 52.1uS. Running this: #include <wiring_private.h> void setup() { // put your setup code here, to run once: pinMode(PF_0, OUTPUT); } void loop() { // put your main code here, to run repeatedly: PWMWrite(PF_0, 256, 200, 15000); } Produces no waveform at all; the signal goes HIGH after Energia starts and then stays there with no transitions.
  48. 1 point

    Sensorless BLDC motor control

    Cool project, I did something very similar as well! https://github.com/lgbeno/BLDC-Booster There is software on there too that you are free to reference. It works with some exceptions. The method that I used for commutation is bemf integration similar to the ti instaspin approach. The issues that I had was that for very fast motors(>500Kv), I wasn't sampling the ADC fast enough to get the commutation timing right but for slow motors, it works great. A few words of wisdom since I worked on this project for quite some time. I would recommend using the 28pin Tssop or qfn32 versions of g2553. Reason being is that it has 3 pins attached to ta1.1 which you can use for the high side pwm signals and 3 pins attached to ta1.2 to be used for low side pwm signals. This does 3 things, frees up timer 0 for something else, allows you to do dead time insertion (if your gate drivers don't already) and just makes your code easier too! The other thing is that you will see your pwm super imposed on your bemf which will likely cause false trips of the comparator. To solve this, there's a low pass filter but that also introduces a dc offset that throws off your zero cross point. Long story short, I came up with a different network that filters and then ac couples the bemf to the comparator. I was seeing pretty good results with that approach. Then I had to return my borrowed scope and have not been able to work on it. Good news is I'm getting a brand new Rigol DS2072 for keeps on Thursday. Anyway I guess that is my project life story, hope it helps. Tomorrow ill try to dig up schematics with those improvements (not in github yet). Btw the schematics are very inspired by the microkoptor.de schematics, mine are as well... I wonder how they got away with the pwm glitches in their software. Obviously theirs works quite well.
  49. 1 point

    OneWire Energia Library

    Unfortunately I haven't heard from Paul Stoffregen yet, so I decided to release the modified source here. I still hope he'll respond, and include the changes in his own library, but at least you guys have a chance to play with it now So, attached is the UNOFFICIAL OneWire library, that is compatible with Energia. Regards, Michel. OneWire Energia Compatible.zip
  50. 1 point
    Rei Vilo

    I2C channels in Stellaris

    Use `setModule()` as described in https://github.com/energia/Energia/blob/master/hardware/lm4f/libraries/Wire/Wire.cpp#L599 void setup() { Wire.setModule(3); Wire.begin(); ... } Similar logic applies for UART and SPI. As an alternative, declare the variable as in https://github.com/energia/Energia/blob/master/hardware/lm4f/libraries/Wire/Wire.cpp#L161 TwoWire Wire2(2);
  • Create New...