Jump to content
43oh

zeke

Members
  • Content Count

    1,782
  • Joined

  • Last visited

  • Days Won

    102

Reputation Activity

  1. Like
    zeke reacted to Rei Vilo in UART using MSP430FR2311   
    Please refer to 25 Functions for 25 Cents: Communication Functions.
  2. Like
    zeke got a reaction from Rei Vilo in Amazon FreeRTOS   
    And the documentation is now FREE!!!
    I paid big bucks for my copy last year!
    Just, Wow!
  3. Like
    zeke got a reaction from Rickta59 in Amazon FreeRTOS   
    And the documentation is now FREE!!!
    I paid big bucks for my copy last year!
    Just, Wow!
  4. Like
    zeke got a reaction from bluehash in Amazon FreeRTOS   
    Apparently, Amazon purchased FreeRTOS!
    Here is a Q&A session with the creator of FreeRTOS - Richard Barry.
    Neato!
  5. Thanks
    zeke got a reaction from Fmilburn in Amazon FreeRTOS   
    I just spotted this on Hackernews:
    https://aws.amazon.com/freertos/
    I am still reading about it but I thought others here would like to know about it. 
  6. Like
    zeke got a reaction from bluehash in Amazon FreeRTOS   
    I just spotted this on Hackernews:
    https://aws.amazon.com/freertos/
    I am still reading about it but I thought others here would like to know about it. 
  7. Like
    zeke reacted to Rei Vilo in I²C Check-List   
    Check the usual suspects:
    Is the I²C bus initialised? Wire.begin(); Does the I²C device run at 3.3V? Otherwise, use a logic-level converter.
    Are pull-ups installed? Try 10, 4.7 or 2.2 kΩ for the SDA and SCL lines.
    In case the LaunchPad provides multiple I²C ports, is the correct port selected? Try 
    Wire.setModule(0); // or other port number Wire.begin(); Still nothing? Use a logic analyser to trace the signals on the I²C port.

    (To be continued...)
  8. Like
    zeke reacted to agaelema in Promotion of MSP430FR2433 MCU LaunchPad™ kit   
    Hi,
    The new MSP430FR2433 ValueLine Launchpad is with a promotional price.
    https://e2e.ti.com/blogs_/b/msp430blog/archive/2017/11/08/introductory-price-of-4-30-for-msp430fr2433-mcu-launchpad-kit?HQS=epd-mcu-msp-vline-fb-blog-LPdiscount-wwe&hootPostID=97a463d63a1e96cbf999f3c7a33c703e
    It seems to be a good replacement to the old ValueLine G2


  9. Like
    zeke reacted to xeebot in More CC3200MOD Questions   
    So, in case anybody else is curious, I've got the answer to my own question.
    Rename your bin to "mcuimg.bin"
    In Uniflash, go to the System Files, find /sys/mcuimg.bin

    Click the BROWSE button for URL and navigate to your file.

    Mark Erase, Update, and Verify.

    Go back to Flash Setup and Control, click Program.

    Enjoy.

    I really have to say that this is fantastic.I'm going to see what functions I can duplicate from CCS this way.
  10. Like
    zeke reacted to energia in BLE Demo Programs   
    Below is a guide to get up and running with Energia BLE / Evothings
    Evothings for controlling your LaunchPad over BLE with a custom app on your mobile device:
     
    I have put together an app that allows to control of the RGB LED and Buttons exposed in the BLEInputOutput Sketch running on the MSP432 LaunchPad. At this moment it only runs on an MSP432 LaunchPad. Other LaunchPad's have bot been tested.
     
    To run the APP and control the LaunchPad follow the instructions below. You might have to upgrade the BoosterPack’s firmware. The firmware on my BoosterPack was not the right one so yours might not be as well. If you have issues running the app, then refer to updating the BoosterPack section below.
     
    Below is a screenshot of the app that I put together using Evothings to control the BLEInputOutput Sketch running on iOS.
     

     
     
    Running the APP on your mobile device:
     
    1: Seat the CC2650 BoosterPack on the MSP432 LaunchPad
    2: You will need the latest BLE library for crucial updates and new example Sketches. Get it from: https://github.com/ti-simplelink/ble_energia
    3: Put the BLE folder in your person Energia/libraries directory just as you would install any other library.
    4: Run Energia and open the example BLE->BLEInputOutput Sketch.
    5: Verify and upload the Sketch
    4: On your phone, download the Evothings Viewer from the app store. There is one for iOS and Android.
    5: Open the app and then in the “Enter connect key” enter http://energia.nu/ble/bleinputoutput/
    6: Click connect.
    7: The Energia BLE app should now open in the viewer. 
    8: Click he start button and the status should change to “Status: Connected”
    9: You can now change the RGB sliders and you should see the LED’s on the LP match
    10: Pressing the buttons will change the text for each button from “released” to “pressed”.
     
     
    Upgrading the CC2650 BoosterPack:
     
    The firmware on your BoosterPack might not be the right one. If you are experiencing issues with running the app, you might have to upgrade the firmware on your CC2650 BoosterPack. We are working on making this cross platform and to accomplish for Energia users. For now Smart RF Flash Programmer 2 has to be used on a windows PC.
     
    1: Download Smart RF Flash Programmer 2
    2: Remove JTAG headers from MSP432 LP (TDI, TDO, TCK, TMS)
    3: Remove the BoosterPack from the LaunchPad (you will need a RED MSP432 LaunchPad)
    4: Attach 10 pin ARM ribbon cable (included in the BoosterPack box) to XDS110 header on the emulation side of the MSP432 LaunchPad. Attach other end to CC2650 BP. It is keyed so there is only one way to attach it.
    5: Get the SNP images from this link: http://software-dl.ti.com/dsps/forms/self_cert_export.html?prod_no=ble_2_02_simple_np_setup.exe&ref_url=http://software-dl.ti.com/lprf/BLE-Simple-Network-Processor-Hex-Files
    6: Once installed, find the image simple_np_cc2650bp_uart_pm_xsbl.hex
    7: Plug the LP into your computer. 
    8: Launch Smart RF Flash Programmer 2.
    9: The CC2650 should show up in the left pane titled “Connected Devices”
    10: Right click the CC2650 and select connect. The status bar should say “Success!” when finished connecting.
    11: On the “Main” tab, in the “Flash Image” field select single and then browse to the simple_np_cc2650bp_uart_pm_xsbl.hex image.
    12: Still on the main tab, under the header “Actions” check “Erase”, “Program” and “Verify”. 
    13: Then click the Green Arrow image on the right bottom to program the image.
    14: Remove the ribbon cable, replace the JTAG headers and reseat the BoosterPack. You are now good to go to run the Sketch/App.
  11. Like
    zeke reacted to BrianCruickshank in MSP430G2553 GUI   
    Yes - you can use GUI Composer 2 (at http://dev.ti.com/gc) to create a GUI for your MSP430G2553 device.  
    You can either use JSON-formatted strings for communicating with the target over the serial port (see http://dev.ti.com/gallery/search/MSP430G2553_LEDs_and_Temp_Demo), or you can use a target-side monitor and communicate over the serial port with the monitor (see http://dev.ti.com/gallery/search/blinky_for_MSP430G2553 ). 
    Regards,
      Brian
  12. Like
    zeke reacted to Fmilburn in All Outputs Go High on Startup   
    Hi @indirtwetrust and welcome to 43oh.
    It always helps to post a simplified version of your code that demonstrates the issue so that others can replicate it.  Perhaps you did not set the pins low before setting them to outputs?  If not, I suspect the default is for Energia is to immediately set output to high.  See the code below where I set pins low first:
     
    /* Test output state on powerup and reset * G2553 LaunchPad without crystal * Energia V17 */ void setup() { pinMode(PUSH2, INPUT_PULLUP); digitalWrite(6, LOW); pinMode(6, OUTPUT); digitalWrite(7, LOW); pinMode(7, OUTPUT); digitalWrite(8, LOW); pinMode(8, OUTPUT); digitalWrite(9, LOW); pinMode(9, OUTPUT); digitalWrite(10, LOW); pinMode(10, OUTPUT); } void loop() { if (digitalRead(PUSH2) == LOW){ digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(8, HIGH); digitalWrite(9, HIGH); digitalWrite(10, HIGH); } else{ digitalWrite(6, LOW); digitalWrite(7, LOW); digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); } } The logic analyzer in the screen shot below is set to capture for 5 seconds.  When I start it, the LaunchPad is running and I am pushing the user button on P1_3, PUSH1, every second or so.  As expected when P1_3 goes low, the output pins go high.

    In the next screen shot I wait about a second into the run to plug in the LaunchPad.  As can be seen, everything is low to start and then P1_3 goes high as soon as it is reached in setup().  The rest stay low.  It takes a while to start up because I don't have the crystal installed on this LaunchPad and Energia tries for a while to start it before giving up.  The same thing if I do a reset - the output pins don't start out high.

     
  13. Like
    zeke reacted to greeeg in GPS logger for a local Beagle club   
    Finally got around to coding a bootloader for this project.
    I'm posting version 0.1 here for reference. Lots of times people seem to have trouble with bootloaders (I put off writing one for ages) But this should show you can start simple, and optimise later.
    The code right now is very rough. But is written in a way that could allow updating of itself it the help of a bootstrap Application. ie: Load new application which when run loads a new bootloader. This bootloader isn't 100% fool proof, if a bad app is loaded that fails to perform as a USB MSC then the user cannot use the USB port to load a new firmware file. but the SD can always be removed and a file copied from a PC if required. Worst case a debugger is required (Which is how they run right now)
    Memory Map
    Here is the memory map I've adopted. The bootloader fits at the top of FLASH, the default reset vector always runs the bootloader. 

     
    The bootloader uses petiet FatFS to read "firmware.bin" off an SD card. It checks the file integrity with a CRC16 integrated into the firmware.bin file on a PC after it was compiled (last word of file). If the file is valid it check the current apps CRC, if they match then app runs. (Application already loaded). If they do not match the Application flash is erased and the new app loaded.
     
    Running the Application
    When launching the app it's CRC is checked to ensure it has loaded correctly. (This shouldn't happen, but you never know...) The App's Interrupt vectors are copied to top of RAM, and SYSCTL.SYSRIVECT is set. The address at the apps reset vector (0xDFFC) is called.
     
    Application changes
    Due to the construction of this bootloader the app needs to have a few changes made, specifically to the linker script. 
    Reduce FLASH boundaries to remove bootloader area Shift Interrupt Vectors to alternate location in flash. (the app doesn't need to know its vectors will be moved to RAM, they just need to be in a fixed location so the bootloader can do that) Remove top 128 bytes of RAM (This is where the new interrupt vectors go. but default this is where the stack is initialised. which will damage the interrupt vectors) Create .crc section (Ensure a fixed WORD is placed to hold our CRC value.)  
    I set up a build setting to output a Binary file format which I run through a simple C program to compute and fill the CRC value. These are all run automatically when the app is built.
    Improvements
    Reduce code size (I have a feeling an SD bootloader could squeeze under 4kb, right now it's at ~6kb) Improve speed, I'm not using the DMA, which could be used to improve speed (Update takes ~10s) Utilise High memory (Right now I'm not enabling the use of high memory, the MSP430F5514 has 17kb in >0x10000 address range.) High memory could be utilised to hold the bootloader this would free up (~7.5kb ) that the Main app could use. gpsLoggerBootloader_0.1.zip
  14. Like
    zeke reacted to maelli01 in Solar power display   
    An output power display for my solar system.
    G2553 Launchpad,  Blue 4-digit LED display, RS485 Transceiver SN65HVD12P (a low power, 3.3V version of the standard SN75176), this is all there is.
    All pins are used,
    4 + 7 for the multiplexed LEDs (no resistors: Blue LED, 3.6V supply, output resistance of the pins limit the LED current)
    3 pins for UART and send/receive for the SN65.
    2 pins for 32768Hz  xtal (I had this one soldered in on the LP, so why not use it)
    The MSP asks the inverter over RS485/Modbus "what is your current output power". After less than half a sec, the  inverter aswers with the required value. This repeats every 2 seconds.
    The inverter is a Fronius Symo, with Datamanager 2 (which I guess is an embedded linux machine, covering LAN, Wifi, Modbus.....).
    The communication protocol can be downloaded from the Fronius website (after signing in), so no reverse engineering was required.
    Instead of only power, I could also display line voltage, frequency, total delivered energy....
     
    This is just a working prototype on Launchpad, I will do a PCB later, I also plan to power this directly from the inverter (which has a 12V solar powered output for such things).
    See the picture, almost 7.5kW :-)
     

  15. Like
    zeke reacted to dubnet in Reducing power consumption in micro SD card.   
    First off, welcome to the forum.
    A couple of ideas come to mind.  The first is that you might want to consider controlling the power to the SD card with a free I/O line and a transistor, only powering it up when you need to write to it.  The other idea is to store multiple samples in an array (which should survive going into low power mode and back) and write them to the SD card every hour or more. How many samples to store between writes to the SD card would depend on your confidence that you wouldn't lose power or have a reset condition before having a chance to move them to the card.
  16. Like
    zeke got a reaction from yyrkoon in Implementing an I2C slave device.   
    Whoops. I forgot that detail. I must be getting old.
    So this is I2C over CANBUS then. Sorta. 
    I have never worked with CANBUS. Can it cover that distance at that speed?
     
  17. Like
    zeke got a reaction from yyrkoon in Implementing an I2C slave device.   
    My gut instincts tell me that your cable will have to be 50 ohm coaxial to get 100kHz over 300 meters. Only super slow speeds can go long distances i.e.: RS-485.
    I would be inclined to use an msp430 on your cape to be the I2C interface master. You could talk to it with the BBB as if it was a slave serial device. That would isolate the BBB from the slow speed pathway. The BBB could just poll the MSP430 for any new data.
     
  18. Like
    zeke got a reaction from yyrkoon in Implementing an I2C slave device.   
    Just in case I didn't make it clear, the speed of the simulated I2C-over-1Wire ends up being about 15kHz. 
    It's not fast but it does work over long lengths of cable and that is pretty darn cool.
  19. Like
    zeke got a reaction from yyrkoon in Implementing an I2C slave device.   
    It was a bit of a mind bender for me at first but then I just read the I2C spec and it did not specify that the communication *had* to be at 100kHz. 
    The way I choose to understand things is that the I2C slave device has a communication state machine inside of it. All I have to do is put in one bit and turn the crank once. Then repeat. Over and over. Then the slave device will just do its job merrily. 
  20. Like
    zeke got a reaction from yyrkoon in CC1350STKUS   
    If they can be setup as a point-to-point link then there shouldn't be any problem setting up a data link between end points.
    Carefully selected and aligned Yagi antennas ought to overcome foliage loss.
  21. Like
    zeke reacted to blankfield in ATX2CHARGER - switch your ATX into a car battery charger with MSP430 [UPDATED]   
    Hi everyone,

    I have idea to use msp430 and hacked atx power supply as a car battery charger. Simply msp430 will be used to control of charge process, different charging current, time, precharging and swichable load for accurate voltage measurement will be available.

    Done:

    * hacked atx to 17V
    * enclosure
    * schematics
    * pcb
    * functional code


    To do:
    * firmware development


    If anyone have some suggestions fell free to post within this topic, I'll be grateful.


    Simple description of operation:

    At first voltage measurement is initiated, user set type of car battery, capacity and charge strategy. While charging is started PWM signal control P-MOSFET to set correct current, feedback is taken from 5mR shunt resistor trough RC low-pass filter and software implementation of 3 order Chebyshev LP filter. Every 5 minutes charge process stops, load resistor is applied and voltage reading is taken. During charge process user can see actual voltage, current, elapsed time and estimated period to end of charging. If battery will be accidentally disconnected mcu stops charging process.  
     
    [uPDATE] 22.12.2012 ======================================================
     
    Results.
     
    ATX2CHARGER is now working, I've successfully charged some car batteries. In near future I need to finish firmware, add rest of options etc. Tomorrow I'll add attachments (sorce of firmware and gerbers).
     
     
    Final schematics:
        PCB:     Tests of working unit:  
     
    All media:
    http://imageshack.us/g/1/9930724/
    http://imageshack.us/g/1/9930688/
     
     
    main.c:
    /*==================================================================== * * ATX2CHARGER v1.0 * 2012 by blankfield <blank0field@gmail.com> * MSP430G2553 @ 16MHz, 3,3V * ===================================================================*/ /*==================================================================== * * headers and includes * ===================================================================*/ #include <msp430.h> #include <ti/mcu/msp430/csl/CSL.h> #include <stdio.h> #include <string.h> #include "msp430g2553.h" #include "main.h" #include "LCD2x16.h" /*==================================================================== * * constants and definitions * ===================================================================*/ //charge indicator animation const char bat0[8] = {0x0A, 0x1F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1F}; const char bat1[8] = {0x0A, 0x1F, 0x11, 0x11, 0x11, 0x11, 0x1F, 0x1F}; const char bat2[8] = {0x0A, 0x1F, 0x11, 0x11, 0x11, 0x1F, 0x1F, 0x1F}; const char bat3[8] = {0x0A, 0x1F, 0x11, 0x11, 0x1F, 0x1F, 0x1F, 0x1F}; const char bat4[8] = {0x0A, 0x1F, 0x11, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}; const char bat5[8] = {0x0A, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}; #define SWSTART BIT7 //P2.7 - START #define SWF1 BIT7 //P1.7 - F1 #define SWF2 BIT6 //P1.6 - F2 #define FIRNtap 15 //fir lp filter number of tap #define Vref (float)3.3 #define ADCRES (float)1023 #define R7resistor (float)4650 #define R9resistor (float)1005 #define R15resistor (float)0.005 #define Uconstant (float)((Vref/ADCRES)*((R7resistor+R9resistor)/R9resistor)) #define Iconstant (float)((Vref/ADCRES)/(R15resistor)) enum enumdisplay_menu {startup, measure_acc, settings, chargeing_params, chargeing_time, summary}; enum enumcharge_type {emergency, normal, mainterance_free}; enum enumaccu_voltage {U6V, U12V}; enum enumstate {idle, charge, discharge}; #pragma DATA_SECTION(ee_charge_type, ".mydata"); #pragma DATA_SECTION(ee_accu_capacity, ".mydata"); #pragma DATA_SECTION(ee_accu_voltage, ".mydata"); #pragma DATA_ALIGN(ee_charge_type, 1); #pragma DATA_ALIGN(ee_accu_capacity, 1) #pragma DATA_ALIGN(ee_accu_voltage, 1); /*==================================================================== * * variables * ===================================================================*/ //FLASH "EEPROM" VALUES unsigned char ee_charge_type; unsigned char ee_accu_capacity; unsigned char ee_accu_voltage; struct timeformat { char hours; char minutes; char seconds; }time; int time_prescale=0; int measurments[4]; float measured_charge_current = 0; float measured_charge_voltage = 0; float measured_discharge_current = 0; float measured_discharge_voltage = 0; float measured_idle_current = 0; float measured_idle_voltage = 0; float Iavg = 0; float Imax = 0; float Ucellmax = 2.5; float Ucelloptimum = 2.4; char accu_capacity = 75; char accu_voltage = U12V; char charge_type = normal; //char charge_time = 0; char charge_progress = 0; char elapsed_1s = false; char tempstring[20]; float DCV[10]; char display_level = startup; char state = idle; /*==================================================================== * * main() * ===================================================================*/ int main(int argc, char *argv[]){ CSL_init();// Activate Grace-generated configuration __delay_cycles(5000); init_mcu(); _delay_cycles(1000000); LCD2x16_Initialize(); __delay_cycles(5000); LCD2x16_WriteCommand(0x01); __delay_cycles(5000); ADC10CTL0 |= ENC;//Start ADC TA1CCR1 = 0; while(1){ control(); if (elapsed_1s){ sprintf(tempstring,"%1.2f;%1.2f;%1.2f;%1.2f;%1.2f;%1.2f;", measured_idle_voltage,measured_idle_current, measured_charge_voltage,measured_charge_current, measured_discharge_voltage,measured_discharge_current); int i; for (i=0; i<sizeof(tempstring); i++) { while (!(IFG2 & UCA0TXIFG)); UCA0TXBUF = tempstring[i]; } elapsed_1s=false; } switch(display_level){ case startup: menu_redraw(); __delay_cycles(25000000); display_level = measure_acc; menu_redraw(); break; case measure_acc: menu_redraw(); if (!(P2IN & SWSTART)) { beep_sound(); display_level=settings; menu_redraw(); } if (!(P1IN & SWF1)) { beep_sound(); if (accu_voltage == U12V) accu_voltage = U6V; else accu_voltage = U12V; menu_redraw(); } break; case settings: if (!(P2IN & SWSTART) && true) { beep_sound(); time.seconds=0; time.minutes=0; time.hours=0; Iavg=0; display_level = chargeing_params; state = charge; menu_redraw(); } if (!(P1IN & SWF1)) { beep_sound(); accu_capacity += 5; if (accu_capacity > 200) accu_capacity = 5; menu_redraw(); } if (!(P1IN & SWF2)) { beep_sound(); charge_type++; if (charge_type>=3) charge_type=0; menu_redraw(); } break; case chargeing_params: if (!(P2IN & SWSTART)) { beep_sound(); display_level=summary; state = idle; menu_redraw(); } if (!(P1IN & SWF1)) { beep_sound(); display_level=chargeing_time; menu_redraw(); } break; case chargeing_time: if (!(P2IN & SWSTART)) { beep_sound(); display_level=summary; state = idle; menu_redraw(); } if (!(P1IN & SWF1)) { beep_sound(); display_level=chargeing_time; menu_redraw(); } break; case summary: if (!(P2IN & SWSTART)) { beep_sound(); display_level=measure_acc; menu_redraw(); } break; } } } /*==================================================================== * * menu_redraw() * ===================================================================*/ void menu_redraw(void){ LCD2x16_GoTo(0,0); switch(display_level){ case startup: LCD2x16_WriteText("ATX2CHARGER v1.0"); LCD2x16_GoTo(0,1); LCD2x16_WriteText(" by blankfield"); break; case measure_acc: if (measured_idle_voltage <=1){ LCD2x16_WriteText("Check battery, "); LCD2x16_GoTo(0,1); sprintf(tempstring,"%01.2fV is too low ",measured_idle_voltage); LCD2x16_WriteText(tempstring); } else{ sprintf(tempstring,"Battery U=%02.2fV ",measured_idle_voltage); LCD2x16_WriteText(tempstring); LCD2x16_GoTo(0,1); //sprintf(tempstring,"P=%01.0f I= %02.2fA ", TA1CCR1*0.05, measured_idle_current); sprintf(tempstring,"Type F1:%02.0dV ",(accu_voltage*6)+6); LCD2x16_WriteText(tempstring); } break; case settings: sprintf(tempstring,"Set cap F1:%03.0dAh ",accu_capacity); LCD2x16_WriteText(tempstring); LCD2x16_GoTo(0,1); if (charge_type==normal) LCD2x16_WriteText("F2: standard "); if (charge_type==mainterance_free) LCD2x16_WriteText("F2: mainter.free"); if (charge_type==emergency) LCD2x16_WriteText("F2: emerg.charg."); break; case chargeing_params: sprintf(tempstring,"U=%02.1fV I=%02.1fA", measured_charge_voltage, measured_charge_current); LCD2x16_WriteText(tempstring); LCD2x16_GoTo(0,1); sprintf(tempstring,"U=%02.1fV I=%02.1fA", measured_discharge_voltage, measured_discharge_current); break; case chargeing_time: sprintf(tempstring,"Elapsed %2.0f:%2.0f:%2.0f", time.hours, time.minutes, time.seconds); LCD2x16_WriteText(tempstring); LCD2x16_GoTo(0,1); sprintf(tempstring,"Iavg=%2.2f ", Iavg); LCD2x16_WriteText(tempstring); break; case summary: LCD2x16_WriteText("Finished! "); LCD2x16_GoTo(0,1); sprintf(tempstring,"%2.0f:%2.0f:%2.0f @ %2.2f", time.hours, time.minutes, time.seconds, Iavg); LCD2x16_WriteText(tempstring); break; } } /*==================================================================== * * control() * ===================================================================*/ void control(void){ switch (state){ case idle: TA1CCR1=0; TA1CCR2=0; break; case charge: TA1CCR2=0; if ((measured_charge_voltage < (Ucelloptimum*3*(accu_voltage+1))) && (measured_charge_current < (accu_capacity/5/(charge_type+1))) && (TA1CCR1<1999)){ TA1CCR1++; } if (((measured_charge_voltage > (Ucelloptimum*3*(accu_voltage+1))) || (measured_charge_current > (accu_capacity/5/(charge_type+1)))) && (TA1CCR1>1)){ TA1CCR1--; } if (TA1CCR1 <=100 && measured_charge_voltage >= (Ucelloptimum*3*(accu_voltage+1))){ state = idle; display_level = summary; beep_sound(); } break; case discharge: TA1CCR1=0; TA1CCR2=1000; break; } } /*==================================================================== * * init_mcu() * ===================================================================*/ void init_mcu(void){ WDTCTL = WDTPW + WDTHOLD; char name[18]="AT+NAMEATX2CHARGER"; int i; for (i=0; i<18; i++) { while (!(IFG2 & UCA0TXIFG)); UCA0TXBUF = name[i]; } } /*==================================================================== * * measure() * interrupts from ADC * ===================================================================*/ void measure(void){ time_prescale++; if (time_prescale==999){ elapsed_1s=true; time.seconds++; //increase every 1s if(time.seconds==60){ time.seconds=0; time.minutes++; if(time.minutes==60){ time.minutes=0; time.hours++; } } } switch (state){ case idle: measured_idle_current = measurments[3]*Iconstant; measured_idle_voltage = measurments[0]*Uconstant; break; case charge: measured_charge_current = measurments[3]*Iconstant; Iavg = (Iavg + measured_charge_current)/2; measured_charge_voltage = measurments[0]*Uconstant; break; case discharge: measured_discharge_current = measurments[3]*Iconstant; measured_discharge_voltage = measurments[0]*Uconstant; break; } return; } /*==================================================================== * * beep_sound() * ===================================================================*/ void beep_sound(void){ TA0CCR1 = 1000; __delay_cycles(500000); TA0CCR1 = 0; return; } /*==================================================================== * * fir() * ===================================================================== WinFilter version 0.8 http://www.winfilter.20m.com akundert@hotmail.com Filter type: Low Pass Filter model: Chebyshev Filter order: 3 Sampling Frequency: 1000 Hz Cut Frequency: 6.000000 Hz Pass band Ripple: 1.000000 dB Coefficents Quantization: float Z domain Zeros z = -1.000000 + j 0.000000 z = -1.000000 + j 0.000000 z = -1.000000 + j 0.000000 Z domain Poles z = 0.981540 + j -0.000000 z = 0.990073 + j -0.036073 z = 0.990073 + j 0.036073 ***************************************************************/ float fir(float NewSample) { float FIRCoef[FIRNtap] = { 0.06499156895458164900, 0.06567519555537033900, 0.06626048168634461600, 0.06674435292740793500, 0.06712913054423083600, 0.06742809591680600000, 0.06768722943723189100, 0.06816788995605341200, 0.06768722943723189100, 0.06742809591680600000, 0.06712913054423083600, 0.06674435292740793500, 0.06626048168634461600, 0.06567519555537033900, 0.06499156895458164900 }; static float x[FIRNtap]; //input samples float y=0; //output sample int n; //shift the old samples for(n=FIRNtap-1; n>0; n--) x[n] = x[n-1]; //Calculate the new output x[0] = NewSample; for(n=0; n<FIRNtap; n++) y += FIRCoef[n] * x[n]; return y; } /*==================================================================== * * flashEraseSegment(int FarPtr) * ===================================================================*/ void flashEraseSegment(int FarPtr){ int *Flash_ptr; // local Flash pointer Flash_ptr = (int *) FarPtr; // Initialize Flash pointer FCTL1 = FWKEY + ERASE; FCTL3 = FWKEY; *Flash_ptr = 0; // dummy write to start erase while (FCTL3 & BUSY ); FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; } /*==================================================================== * * saveSettings(void) * ===================================================================*/ void saveSettings(void){ flashEraseSegment((int) 0xC000); FCTL1 = FWKEY + WRT; FCTL3 = FWKEY; ee_charge_type = (char)charge_type; ee_accu_capacity = (char)accu_capacity; ee_accu_voltage = (char)accu_voltage; FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; } /*==================================================================== * * loadSettings(void) * ===================================================================*/ void loadSettings(void){ charge_type = (char)ee_charge_type; accu_capacity = (char)ee_accu_capacity; accu_voltage = (char)ee_accu_voltage; }  
     
    main.h:
    #ifndef MAIN_H_ #define MAIN_H_ #define false 0 #define true 1 void menu_redraw(void); void control(void); void init_mcu(void); void buttons(void); void measure(void); void beep_sound(void); float fir(float NewSample); void flashEraseSegment(int FarPtr); void saveSettings(void); void loadSettings(void); #endif /* MAIN_H_ */  
    LCD2x16.c:
    // ----------------------------------------------------------------#include "LCD2x16.h"#include "msp430g2553.h"#define RS BIT3 // RS - P2.3 RW - GND#define EN BIT5 // EN - P2.5#define D4 BIT4 // D4 - P1.4#define D5 BIT5 // D5 - P1.5#define D6 BIT0 // D6 - P2.0#define D7 BIT1 // D7 - P2.1//Polish language characters//E6 B9 B3 EA F3 F1 9F 9C A5 BF CA C6 D1 A3 8C D3 AF 8F//? ? ? ? ?






















    atx2charger-firmware.zip
    gerbers-mirror.zip
    gerbers.zip
  22. Like
    zeke reacted to yyrkoon in Random beaglebone code snippets.   
    So, this is partly for me, and partly for others who need a refresher, or just do not know how. But I will be making several post here over time on how to write very simply code, to do one thing, or another. These, used in conjunction with a shell script could be very useful / flexible. After several long talks with many people, including some here on these very forums. I've decided that using C, to communicate with hardware, or hardware interfaces is best as can be for many situations. However, when you need to run several tools all at once, and have output formatted in some fashion, or easily modified. Shell scripts are very good at that sort of thing.
    Read from a real-time clock
    This post I will make about reading from a real-time clock. I spent hours messing around code related to I2C communications, and could never get exactly what I wanted. Plus, I wanted something that output date / time that looked very similar to the date Linux command. This could definitely been done using a shell script, but code size would probably be a lot larger. Additionally, a shell script would very likely be a lot slower, as with a script, one would have to be calling external cmdline tools to perform various operations. This example code is very fast, and prints to screen immediately after issuing the command. Since this command is very simple, and only prints the formatted date / time to screen. This could very easily be called from a shell script, and formatted further if need be.
    The real-time clock I'm using for this demonstration is a Maxim DS3232 real-time clock which is very accurate, and also very expensive compared to other real-time clocks. At $7 + US each, it's not cheap. I also had to write my own device tree overlay for this RTC, which strictly speaking is not necessary. One can set the device up from the command line manually as demonstrated for many different RTC's on the web. In fact, all the device tree overlay that I wrote does, is set all this automatically up at boot. As far as teh actual overlay it's self. All I did was modify an existing overlay from the "official" bb-overlays repo on github. https://github.com/beagleboard/bb.org-overlays/blob/master/src/arm/BB-RTC-01-00A0.dts
    To look something like this:
     
    /* * Copyright (C) 2015 Robert Nelson <robertcnelson@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ /dts-v1/; /plugin/; #include <dt-bindings/board/am335x-bbw-bbb-base.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/pinctrl/am33xx.h> / { compatible = "ti,beaglebone", "ti,beaglebone-black", "ti,beaglebone-green"; /* identification */ part-number = "BB-RTC-01"; version = "00A0"; fragment@2 { target = <&i2c2>; __overlay__ { status = "okay"; /* shut up DTC warnings */ #address-cells = <1>; #size-cells = <0>; /* MCP79410 RTC module */ rtc@68 { compatible = "maxim,ds3232"; reg = <0x68>; }; }; }; }; On our cape, the RTC is on bus I2C-2, which is already enabled by default for capemgr. The rest of the above just means that status is okay(load the device ), the kernel module to load is called "ds3232", and the device address on the bus is 0x68.
    Now on to the actual C code for reading from /dev/rtc1:
     
    #include <stdio.h> #include <stdlib.h> #include <linux/rtc.h> #include <sys/ioctl.h> #include <sys/time.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> void display_date_time(void) { struct rtc_time rtc_tm; int fd = open("/dev/rtc1", O_RDONLY); if(fd == -1){ perror("/dev/rtc"); exit(errno); } /* Read the RTC time/date */ int retval = ioctl(fd, RTC_RD_TIME, &rtc_tm); if (retval == -1) { perror("ioctl"); exit(errno); } int d = rtc_tm.tm_mday; int m = rtc_tm.tm_mon + 1; int y = rtc_tm.tm_year + 1900; const char *wdays[] = {"Sun","Mon","Tues","Wed","Thur","Fri","Sat"}; const char *mnths[] = {"Jan","Feb","Mar","Apr","May","June","July","Aug","Sept","Oct","Nov","Dec"}; int wday = (d += m < 3 ? y-- : y - 2, 23*m/9 + d + 4 + y/4- y/100 + y/400)%7; fprintf(stdout, "%s %s %02d %02d:%02d:%02d %d UTC\n", wdays[wday], mnths[rtc_tm.tm_mon], rtc_tm.tm_mday, rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec, y); } int main( int argc, char **argv ) { display_date_time(); return 0; } As one can see, most of this code is for formatting the output in a specific way. In this case, the output will look exactly like the output one might expect to see after issuing the command "date". However, this output is fixed to output the date / time in the UTC time zone. As for one of the projects I'm using this in is for devices spread out all over the US, in 3 different time zones, and we do not care so much what the local time zone of that system so much, as much as knowing a given time "standard". e.g. if something fails, and we need to tell a customer what failed, and what time it failed, we can, Then if we need to convert that time to their time zone, easy.
    Notice that the read() is handled by ioctl(). . .
     
    Output:
    root@wgd:~/# gcc -Wall -o read_rtc read_rtc.c root@wgd:~/# ./read_rtc Tues May 09 23:08:49 2017 UTC  
  23. Like
    zeke reacted to yyrkoon in Random beaglebone code snippets.   
    Read from a DS18B20 temperature sensor
    Again, very simple code to read from a device, and put that read information out to stdout. In this case, reading from a 1-wire DS18B20 sensor. The pin used is unimportant, so long as that pin is configurable as gpio, and is not already in use by another device. 1-wire is one of the simpler sensors to connect to a beaglebone, and can be plugged directly into one of the two headers on the beaglebone using jumper wires. You need power(3v3), ground, and a gpio pin connected. See the DS18B20 datasheet to determine which pin on the sensor is used for what purpose. As for setup in Linux for this sensor. You can search the web for a guide as to how to do this manually from the cmdline, or you can use a device tree overlay. I used this overlay file as a template, then modified the pin information to reflect the pin I needed to use. https://github.com/beagleboard/bb.org-overlays/blob/master/src/arm/BB-W1-P9.12-00A0.dts
     
    C code:
    #include <stdio.h> #include <dirent.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> int read_DS18B20(void) { DIR *dir; struct dirent *dirent; char dev[16]; char devPath[128]; char buf[80]; char tmpData[6]; char path[] = "/sys/bus/w1/devices"; ssize_t nread; dir = opendir(path); if(dir == NULL){ perror("/sys/bus/w1/devices"); exit(errno); } while((dirent = readdir(dir))){ if (dirent->d_type == DT_LNK && strstr(dirent->d_name, "28-") != NULL){ strcpy(dev, dirent->d_name); } } (void)closedir(dir); sprintf(devPath, "%s/%s/w1_slave", path, dev); int fd = open(devPath, O_RDONLY); if (fd == -1){ perror ("/sys/bus/w1/devices/28-*/w1_slave"); exit(errno); } long tempC = 0; nread = read(fd, buf, 80); if(nread > 0){ strncpy(tmpData, strstr(buf, "t=") + 2, 5); tempC = strtol(tmpData, NULL, 10); } close(fd); return tempC; } int main (void) { float temp = read_DS18B20() * (1 / 1000.0); printf("Temp: %.3f C \n", temp); return 0; } Output:
    root@wgd:~/# gcc -Wall -o read_ds18b20 read_ds18b20.c root@wgd:~/# ./read_ds18b20 Temp: 25.312 C  
  24. Like
    zeke reacted to yyrkoon in Random beaglebone code snippets.   
    How to read an ADC
    So this bit may seem a little odd to some. Hell I know the hardware, and wrote this really quick snippet as a demonstration, and I think it's odd. The short story here. Is that we have a pin multiplexer on AIN6, and this multiplexer selects an external channel based on a bit pattern sent to it through 3 GPIO pins. That code I won't be showing in this post. but I wanted to point out why I have an odd "mvolts" value. Which indicates maximum input voltage before the voltage limiting resistor network. e.g. the on board ADC pins can only handle 1.8v absolute maximum voltage, and I'm pretty sure without all circuitry voltage drop, outside maximum voltage is supposed to be 0-10v, and wulf probably designed the voltage into the ADC it's self to be less than 1.5v . . . So I started with 10v in mind, saw the reading was definitely too high, and then played a guessing game until the voltage I read from a volt meter, matched what I was reading through the ADC. So there is definite resolution loss here . . .
    Anyway, the best and easiest way to load drivers for the ADC is to load the stock ADC overlay from /lib/firmware/.
    root@wgd:~# ls /lib/firmware/ |grep ADC BB-ADC-00A0.dtbo
    That is the file to load. Which can be loaded through capemgr via the command line manually, or from /boot/uEnv.txt at boot.
     
    ADC C code:
    #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> const char *ain6 = "/sys/bus/iio/devices/iio:device0/in_voltage6_raw"; int main() { int fd; int len; char adc[5] = {0}; float madc = 4095.0f; float mvolts = 7.7f; float bvolts = (mvolts / madc); fd = open(ain6, O_RDONLY); if(fd == -1){ perror("ain6"); exit(1); } len = read(fd, adc, sizeof(adc - 1)); int adc_val = strtol(adc, NULL, 10); float voltage = adc_val * bvolts; printf("%f \n", voltage); close(fd); return 0; } Output:
    root@wgd:~# gcc -Wall -o adc adc.c adc.c: In function 'main': adc.c:14:6: warning: variable 'len' set but not used [-Wunused-but-set-variable] int len; ^ root@wgd:~# ./adc 0.030085 A couple things to notice here. First is the warning I'm getting back from the compiler. This is because I'm using the -Wall option, which pretty much tells the compiler to use strict reporting of warnings. It is my belief that one should always at least use the -Wall compiler flag. Then we should treat these warning as if they're errors, and correct them. Which( and yeah I hate explanations like this too ) I'm ignoring for this one situation. Basically "len" is a return value from read() which can let us know how many bytes were read out of the file, and we absolutely should test this value for a non negative number. Then act on negative numbers as an error, which could be done a few different ways. For this demo, I was not sure in a pinch what would be a better way to handle that potential error. Mostly because I know these values will always be 0-4095, unless there is a problem with the hardware. At which point we're done anyhow( probably a blown processor ). One way to deal with this kind of error, would be to use perror() followed by exit(errno) in an if block. But at this point I'm fairly confident the system would not be running anyway . . .However, the values coming out of the ADC module should always be 1-4 characters, so how do we test for no characters ? NULL, but if we're reading out a NULL, how did our code make it thus far anyhow ? Additionally, if we're reading more than 4 character . . .Not only do I believe this to be impossible because of the way I wrote this code, but if it were somehow possible. We'd have a buffer overrun. Which may be a very good idea to test for. If for nothing else, good practice ? You decide.
    Secondly, the really low, but not absolute zero value. Well, I've come to realize that when working with circuits of this nature, that can not tied to ground, or pulled high. You're basically "floating" but close to a low, or a high . . . again, I'm not exactly an EE, so maybe someone who cares to can elaborate further. But I always think of this sort of situation as induced parasitic voltages from the circuitry. I'm definitely all ears if someone has a better explanation, or insight into this. .  .But I've tested these readings against a volt meter, and am reasonably happy that I'm "close enough" for my own purposes. Someday, perhaps I'll buy a USB computer style Oscilloscope, in hopes to enlighten myself further..
  25. Like
    zeke got a reaction from yyrkoon in What is your Backup Process?   
    By the way, I just looked into the cost of a paid github account and the price is $7/month or $84/year.
    That gives you unlimited private repo's.
    Alternatively, gitlab community edition is freely available if you want to self-host. I'm researching this option right now.
×
×
  • Create New...