• Content count

  • Joined

  • Last visited

  • Days Won


Everything posted by spirilis

  1. Hi folks... So I'm a little new to Energia, but since I wrote a library for the nRF24L01+ digital transceivers for native C-based apps I figured it'd be a great idea to port this to Energia. I'm rewriting it from scratch, trying to make it simpler & feel more like a native C++ energia lib. edit: This has been written and the latest version is up on Github. Github project- https://github.com/spirilis/Enrf24 Latest version + comments- http://forum.43oh.com/topic/3237-energia-library-nordic-nrf24l01-library/?p=48805 To that end, I'd like some feedback on the API choices I've made. I want to know what some of you guys think should go in here. For now, here's an example of my "Nrf24.h" class definition (public's only, I haven't drafted the private's and probably won't until I really start writing the code): class Nrf24 { public: Nrf24(uint8_t cePin, uint8_t csnPin, uint8_t irqPin); void begin(); // Defaults used void begin(uint32_t datarate); // Specify bitrate void begin(uint32_t datarate, uint8_t channel); // Specify bitrate & channel void end(); // Shut it off, clear the library's state // I/O boolean available(); // Check if incoming data is ready to be read boolean write(void *buf, uint8_t len); /* Send packet, return true/false for autoACK * (true always if autoACK disabled or 250Kbps rate used) */ uint8_t read(void *inbuf); // Read contents of RX buffer, return length uint8_t read(void *inbuf, uint8_t maxlen); // Read contents of RX buffer up to 'maxlen' bytes, return final length. void autoAck(boolean onoff); // Enable/disable auto-acknowledgements (enabled by default) // Power-state related stuff- void deepsleep(); // Enter POWERDOWN mode, ~0.9uA power consumption void enableRX(); // Enter PRX mode (~14mA) void disableRX(); /* Disable PRX mode (PRIM_RX bit in CONFIG register) * Note this won't necessarily push the transceiver into deep sleep, but rather * an idle standby mode where its internal oscillators are ready & running but * the RF transceiver PLL is disabled. ~26uA power consumption. */ // Custom tweaks to RF parameters, packet parameters void setChannel(uint8_t channel); void setTXpower(int8_t dBm); // Only a few values supported by this (0, -6, -12, -18 dBm) void setSpeed(uint32_t rfspeed); void setCRC(boolean onoff, boolean crc16bit); /* Enable/disable CRC usage inside nRF24's hardware packet engine, * specify 8 or 16-bit CRC. */ // Protocol addressing -- receive, transmit addresses void setAddressLength(uint8_t len); // Valid parameters = 3, 4 or 5. Defaults to 5. void setRXaddress(uint8_t *rxaddr); // 3-5 byte RX address loaded into pipe#1 void setTXaddress(uint8_t *txaddr); // 3-5 byte TX address loaded into TXaddr register // Miscellaneous feature boolean rfSignalDetected(); /* Read RPD register to determine if transceiver has presently detected an RF signal * of -64dBm or greater. Only works in PRX (enableRX()) mode. */ } What do you think? General usage would be to instantiate an Nrf24 object in the global, use begin() to start it and specify some custom params (data rate, or data rate & channel), then the transceiver is just sitting there idle until you either transmit (with setTXaddress() + write()) or enable RX mode with setRXaddress() + enableRX() and poll the available() function periodically. One thing I haven't worked out yet is how to implement the IRQ feature with Energia. The nRF24 has an IRQ pin that is best hooked up for optimal function. Can the library just use attachInterrupt() on the irqPin value that the user passes up top?
  2. Aand. .. Arrow's still doing free shipping, no code needed. $50 minimum for international orders. I'm guessing they're pushing hard to gain a presence in the small-order online commerce arena, but that's good for us! (for now, while shipping is free ) For the most part their online ordering process has improved since last August when I found much to gripe about, and they gave me a contact who manages the web development and I've written him once or twice to report issues I've seen.
  3. Not sure what the JTAG tools run for those, although I think they have a serial bootloader of sorts (the big brother RX series do anyway), and the arch is a modern evolution of the Z80 (taken from NEC when NEC sold their semiconductor division to Renesas) from what I gather. Not important for a smaller chip but, for larger RL78/G14's and such with >64KB flash and/or SRAM, the architecture still uses a 16-bit address bus but with special paging that requires the compiler use "trampoline" code to switch pages as needed (should be transparent to the developer though but adds latency to function calls)..... but, for a super simple program on a small chip, you'll never encounter this. edit: For JTAG, the Renesas E1/E20/etc series of emulators are specified, the cheapest variety is the E2 emulator Lite which is ~$65ish.
  4. Well, I am not sure about the interrupt latency (not that familiar with the arch), and the price is more like $1.50ish... but Renesas RL78/G13 is close: https://www.renesas.com/en-us/products/microcontrollers-microprocessors/rl78/rl78g1x/rl78g13.html https://products.avnet.com/shop/en/ProductDisplay?storeId=715839035&catalogId=10001&langId=-1&productId=3074457345625366633 OK, going down a bit, RL78/G12 has a 24MHz part that's <$1: https://www.renesas.com/en-us/products/microcontrollers-microprocessors/rl78/rl78g1x/rl78g12.html?status=No%3B&pin_count=20%3A20%3B# https://products.avnet.com/shop/ProductDisplay?catalogId=10001&langId=-1&storeId=715839035&productId=3074457345625120989&categoryId=&fromPage=autoSuggest IIRC the compiler is free, or at least there is a GCC port, and Renesas e2studio is a free Eclipse-based IDE.
  5. Happy new year!
  6. Hasn't been tested to rigorous standards demanded by production use cases. Plus TI has to state that to avoid being sued if bad things happened that could be traced back to bugs in Energia. (Not an official explanation)
  7. I thought Energia MT implicitly supported creating multiple tasks by having additional source files with different variations of the setup() and loop() functions e.g. setupRadio() and loopRadio() or similar?
  8. I'm a little embarrassed to admit, but, I had no idea the Linux 'sleep' command could take a decimal point..... always thought it had to use integers. Turns out it takes suffixes for 's' (seconds, the default), 'm' (minutes), 'h' for hours and 'd' for days too! DESCRIPTION Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm' for minutes, 'h' for hours or 'd' for days. Unlike most implementa? tions that require NUMBER be an integer, here NUMBER may be an arbitrary floating point number. Given two or more arguments, pause for the amount of time specified by the sum of their values.
  9. Nope magnification visor w/ extra loupe I can swing down. I think viewing in stereo helps.
  10. Regarding making your own PCB with RF, one nice thing about the TI parts is the TI reference designs, I've used their 2-layer (0.8mm thick) ref design to build a few CC1310 boards of my own, and they work great but the RF passives are all 0402 and require a stencil for solder (OSHStencils stainless works great for this). 0402 is a bear and the absolute lower limit I will go. That said, one of TI's partners made a module for the CC2650 with LGA pads underneath IIRC. That makes the chip far more accessible. Trey German formerly from TI started a small company (Polymorphic Labs) building tiny gadgets based on that module. The CC2650 "BoosterPack" package includes a sample or 2 of that module. But of course all of that is probably over your budget
  11. Well whatever you use, 2.4GHz is best due to PCB antenna size. It is a shame the CC26xx series is too expensive since its high sensitivity would help make the distance even with sketchy small PCB antennas. Also for nRF stuff, I wouldn't bet on those actually making 10m at 2Mbps, but it should at 250Kbps. The issue is the human body and how it may reflect/refract RF as the wearer moves around.
  12. Arrow's still doing free shipping now, all orders USA and $50+ International. Bought a few more components (10x HDC1080, 10x TPS61221 for some CC1310 sensor nodes) to stock the bins.
  13. Without having any way of seeing your breadboard adapter socket soldering job and where the passives are, my first assumption is you probably did something wrong with the chip's layout; FYI this isn't a chip you can casually "solder to an adapter" and expect it to work. It has several passives including an inductor, multiple values of decoupling capacitors, a 24MHz XTAL without load caps (load caps are internal) along with a 32.768KHz XTAL with load caps that are expected (earlier revisions of the CC1310 chip couldn't run without the 32.768KHz XTAL). I've been successful in rolling my own boards by designing them from scratch but closely following the layout decisions demonstrated by TI's own reference designs.
  14. I personally won't touch anything other than the F128 model. I think it was a mistake for TI to produce them (especially the CC1310F32, like, wtf?)... with the RTOS being an integral part of the solution.
  15. That confirms some suspicions many have had... the CCS license bundling w/ launchpads was a clever way to sell some hardware. Why would the TI ARM compiler go away? I haven't done an exhaustive analysis on it but I have to imagine TI built it for a reason. The real news here is the MSP430 optimizing compiler having no code limit (I assume...) Of course maybe a bit too late now that msp430-elf-gcc has been around a while.
  16. That's awesome, I didn't know about that.
  17. I think #1 is going to make a handful of folks happy, and practically might work for a lot of people, but it's not "sexy" in my opinion. That said I am doing my own Network Processor interface firmware but only for the "base station" application--hooking it up to a Raspberry Pi 3 in my instance. The remote nodes will all run firmware directly on the CC1310. I'm curious if there's any interpreted languages worth considering, like Forth or Lua. Never used either of them personally but the "era of tiny programmable radio nodes" is really upon us with the tech enabled by these chips. My own stuff will be C atop TI-RTOS for now.
  18. You changed the TX power before initialization right? (I think the txPower field has to be set before the Frequency Synthesizer is programmed... IIRC... well unless your setTxPwr implementation does a CMD_FS reprogram itself)
  19. What TX power are you using?
  20. I am happy I used a couple opportunities (when I had more surplus cash than originally budgeted) to buy these kinds of tools... a Saleae Logic16 about 3yr ago, and a DS1054z this past July. Cause I hear @@yyrkoon 's dilemma, it's a pain to have the need for these tools while one is constrained on cash. Moral of the story: Sometimes it *does pay* to make seemingly frivolous investments in quality tools when you don't appear to need them. It's a gamble every time but certain tools are worth having. Like my 22gal air compressor in the garage, it's not strictly necessary for DIY car work but oh does it make certain situations palatable to deal with.
  21. yeah, I can imagine you don't need the timer for output, since the CPU can time its execution as needed based on interrupts or polling a timer and just manually flip the GPIO.
  22. yep- (Page 3, Device Pinout) See how (in the 20-pin variant) pin 9 says "P2.1/TA1.1" ... Timer_A1 CCR#1 is its alternate function (with P2SEL |= BIT1, P2SEL2 &= ~BIT1) Also P2DIR needs configuring (P2DIR &= ~BIT1) to make it an input (CCI): (page 51, Port 2 schematics)
  23. The idea is to have the RX pin just happen to be one of the pins with a Timer_A association capable of doing capture, preferably a TA0.1 or TA0.2 or TA1.1 or TA1.2 type of thing. Not sure if it would work with TA0.0 or TA1.0. Then you can use the timer to capture the moment of transition for that pin which should assist in detecting pulses. I've never written a software UART myself so I'm not sure what all is involved, but that one little piece I do know. It might also be beneficial to have the TX pin going to another TA0.[1+] or TA1.[1+] pin too for output but I'm not 100% sure.
  24. Picking this forum for a blog thread on learning the "ropes" of FreeRTOS. TM4C123 launchpad is my learning board for now, using CCSv6 under Windows, latest FreeRTOS and the GNU GCC compiler that ships with CCS (Linaro). From a fresh download of FreeRTOS, I finally have a working example (not relying on "importing" a CCS example and modifying it - you learn more this way). Here's main.cpp with all the init + task code: /* * main.c */ #include <FreeRTOS.h> #include <task.h> #include <timers.h> #include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" void UsrSW1_Monitor(void *); int main(void) { MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)) ; MAP_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD); if (pdTRUE != xTaskCreate(UsrSW1_Monitor, "Pushbutton_Monitor", 48, NULL, 3, NULL)) { // Crash due to insufficient heap memory? MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2); // Illuminate R+B for purple while(1) ; } //xTaskCreate(NullTask, "Nothing", 48, (void *)1, 4, NULL); vTaskStartScheduler(); // If FreeRTOS ever exits, illuminate orange (R+G) MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_3); while(1) ; return 0; } void BlinkyTask_LEDBlink(void *pvParams) { unsigned int whichLed = (unsigned int)pvParams; uint8_t whichBit = 1 << whichLed; uint8_t currentValue = 0; while (1) { currentValue ^= whichBit; MAP_GPIOPinWrite(GPIO_PORTF_BASE, whichBit, currentValue); vTaskDelay(250 / portTICK_RATE_MS); } } void UsrSW1_Monitor(void *pvParams) { uint16_t inputShifter = 0; bool inputLatched = false; const uint32_t USR_SW1 = GPIO_PIN_4; // PF4 uint8_t whichLed = 1; xTaskHandle blinkerTask; // Start blinker task with current whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } while (1) { // Poll USR_SW1 GPIO - active LOW if (MAP_GPIOPinRead(GPIO_PORTF_BASE, USR_SW1)) { inputShifter <<= 1; } else { inputShifter <<= 1; inputShifter |= 1; } // Test if button has been pressed or released if ( !inputLatched && (inputShifter & 0xF0) == 0xF0 ) { // Rotate LED whichLed++; if (whichLed > 3) { whichLed = 1; } // Kill blinker task vTaskDelete(blinkerTask); // Switch off all LEDs MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, 0); // Start new blinker task with new whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } // Latch button press so we don't re-trigger until button has been released inputLatched = true; } if ( inputLatched && (inputShifter & 0xFF) == 0 ) { inputLatched = false; // un-latch USR_SW1 } // Wait 10ms before checking again vTaskDelay(10 / portTICK_RATE_MS); } } Result: Red LED blinks, left pushbutton toggles to blue & green and back to red. Pressing & holding the pushbutton switches the LED but only once, as the pushbutton task "latches" it. The technique of debouncing a pushbutton using periodic polling + bit shifts and logic tests was something I saw on hackaday recently - http://hackaday.com/2015/12/10/embed-with-elliot-debounce-your-noisy-buttons-part-ii/ I didn't use the same test values but it doesn't matter... Using polling instead of interrupt for the pushbutton is definitely one of those things that is easy & practical only if using an RTOS.
  25. As an addendum, I suspect the MSP430's interrupt features such as the ability to determine return LPM status (__bic_SR_register_on_exit()) and its small size firmly plants the MSP430 in the realm of that which doesn't need an RTOS and where an RTOS is probably not desirable. Its small size and specific feature sets make it optimal for simpler systems where "real time constraints" are enforced either by peripheral features or by individual interrupts, and the main execution thread is the lowest-priority "idle" task. The use of volatile variable flags (semaphores if you will) to synchronize features inside your main execution thread can be used to run background post-processing operations off a while() loop inside your main(), after which an LPM mode is entered to save power.