Jump to content

GeekDoc

Members
  • Content Count

    1,391
  • Joined

  • Last visited

  • Days Won

    13

Reputation Activity

  1. Like
    GeekDoc reacted to enl in [ ENDED ] Oct 2013 - 43oh Halloween Contest   
    Took the challenge. Started monday when I got home from work.
     
    Project is spooky eyes for the bushes. 8 channels, each of which will drive approx 3 amps, which is abou 110LEDs from the the 12V LED strip I used.
     
    Cut the strip into three LED sections (the minimum for this type), soldered on 300mm lead sets (twisted pair from cat5 cable), and used epocy to ttach the leds to ping pong balls. bent the strip so the LEDs fit flush to the surface. The epoxy provides good coupling, so, before painting, the balls had a good bright red glow.
     
    Masked pupils and painted the balls black with the cheapest spray I had on hand. Several coats to block waster light. The LEDs leak a lot to the side.
     
    Threw the code together in about an hour. Three modes.
     
    Interesting part of the code is the method for not caring about the timing. It dosen't much matter if a PWM tick is missed the start of the cycle, as if the LED is off, it stays off. If it is on, it makes dimmest setting one tick brighter. Therefore, I put the whole mess into the interrupt routine and counted the PWM myself, rather than use the timer features, so that I could run 8 PWM's off one interrupt with several modes. The trick is to build the NEXT PWM state during the tick, and set the outputs first thing on the interrupt. Also, only do the work for the PWM pulse length once per cycle, which may lengthen the first tick, but it will be consistant and not mess up the overall appearance in operation. Could've upped the clock to buy more cycles, but it won't look any better. for the uploaded program, the first tick of the cycle, when the updates are done, just misses over-running. If all outputs were set to mode 2 (more conditions), I think it does, but it looks fine in practice.
     
    I used P2 for output so I could use the launchpad LEDs during testing, and was going to use the other pins for input to change modes. I got lazy. May do it later.
     
    The drivers are TIP31's to ground. Simple, and I had them in the stockpile. Mounted on a scrap of vectorboard from an old S100 bus A/D from when I was working in the medical lab.
     
    Pics are the eyeballs hanging to dry; channel schematic; shot of the launchpad, channel drivers (second piece not yet mounted), terminal strip, and power supply liberated from an old external hard drive that powers the mess; a couple shots of the eyes in the shrubs; code; and link to video of operation will follow when I upload it (youtube accound came from the Google+ name I got when I bought a nook. Didn't habe one, and the doofus at B&N made it for me without telling me without telling me. As you will see, he was quite creative in making up a name, seeing as how he had mine in front of him, as well as me standing there) The eyes are not visible, once twilight hits, unless they are on, nor are the twisted pairs from the cat5.
     
    Video link will be posted when I get done with youtube. BTW: schematic not bad for MSpaint, no? Don't have good schematic software on this machine...
     
    EDIT: link to video:
     
    EDIT 2: revised code is attached as main-revised. Moved text of followup here. Left original main as I can not bury my sins in good conscience
    -------------------------------------
     
    Found an hour and made the code a bit more presentable.
     
    Function control is in the main, and only the PWM setup is in the interupt routine. Also, bushbutton on launchpad acts as circuit test: Pushing it turns all channels on (well, mostly. The PWM interrup my shut off a channel for the duration of the interrupt routine) for checking the wireup.
     
    Also, modified the structure for each function to allow a bit more user tuning: The length of each operation can be varied for each channel.
     
    I didn't put the processor to sleep when the updates are completed. A few hundred microwatts for the processor when the LED's are using 10 or more watts (max without modification to code or hardare is about 250W) isn't really significant.\
     
    This update is not really any more elegant than the original, but it is structured better.... I am less embarrassed by the code now.






    main.c
    main-revised.c
  2. Like
    GeekDoc reacted to RobG in 10W & 20W RGB LED driver board   
    Here's a different version of the 3ch constant current driver.
    It can deliver up to 1.2A per channel.
    PWM input for brightness control.
    Current can be selected using 3 jumpers, each channel separately, 7 possible values (for example 1A, 0.8A, 0.7A, 0.5A, 0.3A, and 0.2A.)
     
    Available on Tindie
     

  3. Like
    GeekDoc reacted to bluehash in Nov-Dec 2013 Project of the Month Sponsors/Planning   
    We have another 43oh POTM Sponsor - Saelig Electronics. Welcome!
     
    Saelig is a Sales and Marketing Agent and Distributor for more than 100 manufacturers from all over the world. Founded in 1988 by Alan Lowne, Saelig has earned a growing reputation for having notable products not found elsewhere.
  4. Like
    GeekDoc reacted to Fred in Animated Darth Vader build monitor   
    At work we use Continuous Integration to build and test our code as we check it in. It helps catch problems early and ensures we keep code standards up. We were using CruiseControl.NET but have now moved to TeamCity. Anyway, this is no use unless people take notice of broken builds and this was starting to slip. I decided that something fairly visible (but not too annoying) was needed. After spotting a Lego Dath Vader toy torch it seemed like a good solution.
     
    The standard toy has a button on his chest that is used to switch on some while LEDs in his feet. There was also a red LED and a AAA battery in his lightsaber so it could be switched on. The plan was to add a servo to his arm so he could wave the lightsaber around and replace the red LED with a RGB one so that the colours could change. All of this under PC control of course.
     
    Rather than describe in in boring detail exactly what I did, I hope some photos of the progress will sum it up. First I had to get a servo in place operating his right arm. It required cutting away the battery compartment, filing the joint to make it a little easier to move and hot-gluing the servo in place.
     
     
     
    The front just involved making a bit more room to glue the servo in. The a slot needed to be carefully added for the servo horn to drive the arm. The horn was later screwed to the servo. The connection between the servo horn and teh shoulder joint is just a push fit.
     
     
     
    For the lightsaber, the battery, connectors, original PCB and LED had to be removed. The switch was glued in place as it wasn't to be used but needed to fill the hole. As ther was no PCB to locate the new LED, it was glued into place. Running the 4 wires from the RGB LED involved carefully drilling a path through the side of the lightsaber, the hand, arm and shoulder joint. I had to be careful that the wires coming out of the shoulder didn't limit the servo movement.
     
     
      
     
     
    The next step was putting all this under PC control. I decided that the recently release MSP430F5529 Launchpad would make be ideal due to the built-in USB functionality. It could easily handle a few PWM channels. All that was required was to connect ground, 5V and a PWM signal to the servo and 3 PWM signals to the channels of the LED. I wasn't going to drive the LED directly from the MSP430 pins, but to use a P channel MOSFET and a NPN transistor as a high side switch (for the common cathode LED). However it seems that the F5549 can handle a little more than the spec sheet says. I was lazy and just drive them via some 100 ohm resistors. The photo also shows the clear acrylic base (cut using a 40W CO2 laser cutter) and a 3D printed enclosure for the Launchpad.
     
     
     
     
    A small home etched PCB is underway so that it will just need a USB cable to his back rather than the bulky external Launchpad. Whether this phase 2 gets overtaken by other projects or not though - that's a good question.
     
    The connection between the device and the PC is using a USB serial port. The code is adapted from the sample CDC COM port code for the Launchpad. I used TA0.2 to TA0.4 for the LED PWM as these are easily accessible on the Launchpad. I used TA2.1 for the servo as this was conveniently close to the 5V supply needed for the servo.
     
     
    As far as what controls Darth Vader, I tried a number of options. Initial control was done from an ASP.NET MVC web page. Anyone in the office could control him with simple URLs like fredpc/Vader/Colour/Blue or fredpc/Vader/Position/0. The connection to TeamCity proved a little more difficult. I started work on a Java plug-in for TeamCity that woudl call these URLs, but it was a pain to get the plug-in installed and working in TeamCity. All the documentation I could find was out of date and incosistent - as is often the case with Java. I ended up going with a Windows service that polls TeamCity (using Rest APIs) every 10 minutes.
     
    I you'd like to see it working, here are a couple of videos of it in action.


     
     
    Well, I'm entering this is the Halloween contest - you can even see 43oh in the background in the second video. I hope it's Halloweeny enough, because strictly speaking it's a project that I did to use at work. It's in action right now monitoring our TeamCity build server. In fact the MD of the company wandered past my desk this afternoon to ask why Darth Vader was red. It's a bit scary being under that sort of pressure to fix any broken unit tests, but that was kind of the point...
     

    /* --COPYRIGHT--,BSD * Copyright (c) 2013, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ /* * ======== main.c ======== * Darth vader control: * * This code has been adapted from TI's cample CDC COM port code * ---------------------------------------------------------------------------*/ #include <string.h> #include "inc/hw_memmap.h" #include "gpio.h" #include "wdt_a.h" #include "ucs.h" #include "pmm.h" #include "sfr.h" #include "timer_a.h" #include "USB_config/descriptors.h" #include "USB_API/USB_Common/device.h" #include "USB_API/USB_Common/types.h" // Basic Type declarations #include "USB_API/USB_Common/usb.h" // USB-specific functions #include "USB_API/USB_CDC_API/UsbCdc.h" #include "USB_app/usbConstructs.h" /* * NOTE: Modify hal.h to select a specific evaluation board and customize for * your own board. */ #include "hal.h" // Function declarations BYTE retInString (char* string); // Global flags set by events volatile BYTE bCDCDataReceived_event = FALSE; // Indicates data has been rx'ed // without an open rx operation #define MAX_STR_LENGTH 64 char wholeString[MAX_STR_LENGTH] = ""; // Entire input str from last 'return' BYTE wildcardMatch (char* string, char* match); void send(const char* message); void initServo(void); void stopServo(void); void setServo(unsigned char duty); void parseAndSetServoPosition(char positionText); void setServoOffTimer(void); void initRgbLed(void); void setRgbLed(unsigned char red, unsigned char green, unsigned char blue); void parseAndSetColour(char* colourText); void vaderTest(void); unsigned char getHexDigit(char text); const unsigned int ServoPeriod = 655; // = 32768 / 50 = 20ms; const unsigned int positions[] = {30,34,38,42,46,50,54,58,62,66}; // 0.9 to 2.1ms /* * ======== main ======== */ VOID main (VOID) { WDT_A_hold(WDT_A_BASE); // Stop watchdog timer // Minumum Vcore setting required for the USB API is PMM_CORE_LEVEL_2 . PMM_setVCore(PMM_BASE, PMM_CORE_LEVEL_2); initPorts(); // Config GPIOS for low-power (output low) initClocks(8000000); // Config clocks. MCLK=SMCLK=FLL=8MHz; ACLK=REFO=32kHz USB_setup(TRUE, TRUE); // Init USB & events; if a host is present, connect initRgbLed(); initServo(); // Setup servo PWM __enable_interrupt(); // Enable interrupts globally while (1) { BYTE i; // Check the USB state and directly main loop accordingly switch (USB_connectionState()) { // This case is executed while your device is enumerated on the // USB host case ST_ENUM_ACTIVE: // Enter LPM0 (can't do LPM3 when active) __bis_SR_register(LPM0_bits + GIE); _NOP(); // Exit LPM on USB receive and perform a receive operation // If true, some data is in the buffer; begin receiving a cmd if (bCDCDataReceived_event){ // Holds the new addition to the string char pieceOfString[MAX_STR_LENGTH] = ""; // Holds the outgoing string char outString[MAX_STR_LENGTH] = ""; // Add bytes in USB buffer to the string cdcReceiveDataInBuffer((BYTE*)pieceOfString, MAX_STR_LENGTH, CDC0_INTFNUM); // Get the next piece of the string // Append new piece to the whole strcat(wholeString,pieceOfString); // Echo back the characters received cdcSendDataInBackground((BYTE*)pieceOfString, strlen(pieceOfString),CDC0_INTFNUM,0); // Has the user pressed return yet? if (retInString(wholeString)){ if (!(strcmp(wholeString, "TEST"))) { vaderTest(); } else if(wildcardMatch(wholeString,"POSITION ?")) { parseAndSetServoPosition(wholeString[9]); } else if(wildcardMatch(wholeString,"COLOUR #???")) { parseAndSetColour(wholeString+8); } else if(wildcardMatch(wholeString,"ALL ?#???")) { parseAndSetServoPosition(wholeString[4]); parseAndSetColour(wholeString+6); // Handle other } else { // Prepare the outgoing string strcpy(outString,"\r\nNo such command!\r\n\r\n"); // Send the response over USB cdcSendDataInBackground((BYTE*)outString, strlen(outString),CDC0_INTFNUM,0); } // Clear the string in preparation for the next one for (i = 0; i < MAX_STR_LENGTH; i++){ wholeString[i] = 0x00; } } bCDCDataReceived_event = FALSE; } break; // These cases are executed while your device is disconnected from // the host (meaning, not enumerated); enumerated but suspended // by the host, or connected to a powered hub without a USB host // present. case ST_PHYS_DISCONNECTED: case ST_ENUM_SUSPENDED: case ST_PHYS_CONNECTED_NOENUM_SUSP: //Turn off LED P1.0 GPIO_setOutputLowOnPin(LED_PORT, LED_PIN); __bis_SR_register(LPM3_bits + GIE); _NOP(); break; // The default is executed for the momentary state // ST_ENUM_IN_PROGRESS. Usually, this state only last a few // seconds. Be sure not to enter LPM3 in this state; USB // communication is taking place here, and therefore the mode must // be LPM0 or active-CPU. case ST_ENUM_IN_PROGRESS: default:; } } // while(1) } // main() /* * ======== UNMI_ISR ======== */ #pragma vector = UNMI_VECTOR __interrupt VOID UNMI_ISR (VOID) { switch (__even_in_range(SYSUNIV, SYSUNIV_BUSIFG)) { case SYSUNIV_NONE: __no_operation(); break; case SYSUNIV_NMIIFG: __no_operation(); break; case SYSUNIV_OFIFG: UCS_clearFaultFlag(UCS_BASE, UCS_XT2OFFG); UCS_clearFaultFlag(UCS_BASE, UCS_DCOFFG); SFR_clearInterrupt(SFR_BASE, SFR_OSCILLATOR_FAULT_INTERRUPT); break; case SYSUNIV_ACCVIFG: __no_operation(); break; case SYSUNIV_BUSIFG: // If the CPU accesses USB memory while the USB module is // suspended, a "bus error" can occur. This generates an NMI. If // USB is automatically disconnecting in your software, set a // breakpoint here and see if execution hits it. See the // Programmer's Guide for more information. SYSBERRIV = 0; //clear bus error flag USB_disable(); //Disable } } BYTE wildcardMatch (char* string, char* match) { char s; char m; BYTE i; for (i=0; i < MAX_STR_LENGTH; i++) { s = string[i]; m = match[i]; // No match if (s != m && m != '?') return(FALSE); // Reached the end if (s == 0 || m == 0) { // of both? return (s == m); } } // Catch any overrun return (FALSE); } /* * ======== retInString ======== */ // This function returns true if there's an 0x0D character in the string; and if // so, it trims the 0x0D and anything that had followed it. BYTE retInString (char* string) { BYTE retPos = 0,i,len; char tempStr[MAX_STR_LENGTH] = ""; strncpy(tempStr,string,strlen(string)); // Make a copy of the string len = strlen(tempStr); // Find 0x0D; if not found, retPos ends up at len while ((tempStr[retPos] != 0x0A) && (tempStr[retPos] != 0x0D) && (retPos++ < len)) ; // If 0x0D was actually found... if ((retPos < len) && (tempStr[retPos] == 0x0D)){ for (i = 0; i < MAX_STR_LENGTH; i++){ // Empty the buffer string[i] = 0x00; } //...trim the input string to just before 0x0D strncpy(string,tempStr,retPos); //...and tell the calling function that we did so return ( TRUE) ; // If 0x0D was actually found... } else if ((retPos < len) && (tempStr[retPos] == 0x0A)){ // Empty the buffer for (i = 0; i < MAX_STR_LENGTH; i++){ string[i] = 0x00; } //...trim the input string to just before 0x0D strncpy(string,tempStr,retPos); //...and tell the calling function that we did so return ( TRUE) ; } else if (tempStr[retPos] == 0x0D){ for (i = 0; i < MAX_STR_LENGTH; i++){ // Empty the buffer string[i] = 0x00; } // ...trim the input string to just before 0x0D strncpy(string,tempStr,retPos); // ...and tell the calling function that we did so return ( TRUE) ; } else if (retPos < len){ for (i = 0; i < MAX_STR_LENGTH; i++){ // Empty the buffer string[i] = 0x00; } //...trim the input string to just before 0x0D strncpy(string,tempStr,retPos); //...and tell the calling function that we did so return ( TRUE) ; } return ( FALSE) ; // Otherwise, it wasn't found } /* * Switch the servo off after it's settled to stop the hum */ void setServoOffTimer(void) { // Use Timer A1 for a one-shot interrupt TA1CCTL0 = CCIE; // CCR1 interrupt enabled TA1CCR0 = 32768; // About 1s TA1CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, up mode, clear TAR } // Timer0 A1 interrupt service routine #pragma vector=TIMER1_A0_VECTOR __interrupt void TIMER1_A0_ISR(void) { // Stop servo TA2CCR1 = 0; // Stop timer TA1CTL = TASSEL_0 + MC_1 + TACLR; } void parseAndSetServoPosition(char positionText) { if (positionText < '0' || positionText >'9') { stopServo(); send("\r\nArm servo off\r\n\r\n"); return; } setServo(positionText - '0'); send("\r\nArm servo position set\r\n\r\n"); } void initServo(void) { GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4); TIMER_A_clearTimerInterruptFlag(TIMER_A2_BASE); //Generate PWM - Timer runs in Up-Down mode TIMER_A_generatePWM(TIMER_A2_BASE, TIMER_A_CLOCKSOURCE_ACLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, ServoPeriod, TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_RESET_SET, 0); } void stopServo(void) { TA2CCR1 = 0; } void setServo(unsigned char position) { if (position > 9) { stopServo(); } else { TA2CCR1 = positions[position]; setServoOffTimer(); } } /* * Uses Timer A0 for 3PWM output * Chosen as these are accessible on LaunchPad * TA0.2 on P1.3 * TA0.3 on P1.4 * TA0.4 on P1.5 */ void initRgbLed(void) { P1DIR |= BIT3 + BIT4 + BIT5; // P1.3, P1.4 and P1.5 output P1SEL |= BIT3 + BIT4 + BIT5; // P1.3, P1.4 and P1.5 options select TA0CCR0 = 0xFE; // PWM Period TA0CCTL2 = OUTMOD_7; // CCR2 reset/set TA0CCR2 = 0; // CCR2 PWM duty cycle initially 0 TA0CCTL3 = OUTMOD_7; TA0CCR3 = 0; TA0CCTL4 = OUTMOD_7; TA0CCR4 = 0; TA0CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, up mode, clear TAR } void setRgbLed(unsigned char red, unsigned char green, unsigned char blue) { // Set PWM registers TA0CCR2 = red; TA0CCR3 = green; TA0CCR4 = blue; } void parseAndSetColour(char* colourText) { unsigned char red = getHexDigit(colourText[0]); unsigned char green = getHexDigit(colourText[1]); unsigned char blue = getHexDigit(colourText[2]); if (red == 255 || green == 255 || blue == 255) { send("\r\nUnrecognised colour"); return; } red *= 0x11; green *= 0x11; blue *= 0x11; // Set PWM registers setRgbLed(red, green, blue); send ("\r\nColour set\r\n"); } void vaderTest() { setServo(0); unsigned char x; // red for (x=0; x < 255; x++) { setRgbLed(x, 0, 0); __delay_cycles(50000); } setServo(1); // --> yellow for (x=0; x < 255; x++) { setRgbLed(255, x, 0); __delay_cycles(50000); } setServo(2); // --> green for (x=255; x; x--) { setRgbLed(x, 255, 0); __delay_cycles(50000); } setServo(3); // --> green/blue for (x=0; x < 255; x++) { setRgbLed(0, 255, x); __delay_cycles(50000); } setServo(4); // --> blue for (x=255; x; x--) { setRgbLed(0, x, 255); __delay_cycles(50000); } setServo(5); // --> purple for (x=0; x < 255; x++) { setRgbLed(x, 0, 255); __delay_cycles(50000); } setServo(6); // --> red for (x=255; x; x--) { setRgbLed(255, 0, x); __delay_cycles(50000); } setServo(7); // --> off for (x=255; x; x--) { setRgbLed(x, 0, 0); __delay_cycles(50000); } setServo(0); setRgbLed(0,0xFF,0); __delay_cycles(5000000); setServo(9); setRgbLed(0xFF,0,0); __delay_cycles(5000000); setServo(0); setRgbLed(0,0,0); } unsigned char getHexDigit(char text) { if ((text >= '0') && (text <= '9')) return (text-'0'); if ((text >= 'A') && (text <= 'F')) return (10 + text-'A'); if ((text >= 'a') && (text <= 'f')) return (10 + text-'a'); return 255; } void send(const char* message) { /* // Holds the outgoing string char out[MAX_STR_LENGTH] = ""; // Prepare the outgoing string strcpy(out, message); // Send the response over USB cdcSendDataInBackground((BYTE*)out, strlen(out),CDC0_INTFNUM,0); */ } //Released_Version_4_00_00  
  5. Like
    GeekDoc reacted to bluehash in Nov-Dec 2013 Project of the Month Sponsors/Planning   
    Good News! Panavise came back to us with a sponsorship prize for the POTM and also bought some ad-space. A big thank you to them. Very much appreciated!
    All the items below can be purchased from Panavise.com . The 201+ package below can be put together to make a perfect workstation for your boards.
     
    $26 - PanaVise Model 201 "Junior" Miniature Vise
    $23.99 - PanaVise 312 Tray Base Mount
    $16.99 - PanaVise 371 Solder Station(includes soldering iron holder, spool holder and nib sponges)
    $2.69 - PanaVise 239 Speed Control Handle for 201, 203, 207 and 209
    $3.49 - PanaVise 204 Neoprene Pads
     
    Total Panavise Sponsorship - $73.16
     

  6. Like
    GeekDoc reacted to Fred in Nov-Dec 2013 Project of the Month Sponsors/Planning   
    I'd like to donate something. I've been collecting toys lately and I'm lucky enough to have a 3D printer and a laser cutter. I'd be happy to print/laser something. The winner can email me the design for what they want. I'll make it and ship it.
  7. Like
    GeekDoc got a reaction from bluehash in Kimco Project of the Month Giveaway Ideas   
    Depending on the level they want to sponsor, any basic supplies would be great:
     
    -Flux pen(s), desolder wick,
    -Side cutters, soldering accessories
    -Bench magnifier, multimeter, solder iron/station
  8. Like
    GeekDoc reacted to Fred in [ ENDED ] Oct 2013 - 43oh Halloween Contest   
    I'm on it. I'll document it properly over the nest few days, but if you just want a peek at the finished item it's here:  Hope it's Halloweeny enough.
  9. Like
    GeekDoc reacted to mpymike in MPY Halloween Ghost Project   
    MPY Halloween Ghost Project
     
    This project is a scary ghost for halloween. It is setup in the front garden to scare away the hordes of trick-or-treaters.
    When a passing trick-or-treater approaches the ghost will scream and move back and forth along side the garden path.
     
    It uses two MSP430s, One for the Ghost to detect passing trick-or-treaters and a second MSP430 to pull the Ghost on a loop of string. See it in action in the video.
     
     


     
     
    The Ghost
     
    The msp430 in the ghost is mounted onto a breadboard with a battery pack stuck to the back.
    An HC-SR04 ultrasonic detector is used to detect objects between 5-8 feet away. The sound comes from a 1.5" 100 ohm speaker from pololu.com and a random flashing high intensity LED are used to frighten away anyone who approaches too close.
     
    I used a low cost 433MHz RF TX module from elecrow.com to send a signal to the pully motor controller. This worked very well it had plenty of range once I added a 12" length of wire as an antenna.
     

     
    The circuit is pretty simple. I used a 4.5v battery pack and a diode to drop the supply for the MSP430 to a safer level. The TX module and the ultrasonic detector needed the higher supply voltage.  I found the HC-SR04 ultrasonic detector to be quite difficult to use. It had a lot of dead positions where it would not detect reliably, (could probably be caused by multipath reflections giving false echos). I had to
    make the code detect echos that were within a narrow range.
    The speaker is driven directly from the MSP430 timer output. Frequency being controlled by the timer period and the volume controlled by the pulse width. 
     
     
    The circuit is mounted onto a breadboard. The ultrasonic module was a bit floppy and needs to be held in place firmly as the whole thing gets shaken around quite a bit. it isn't very permanent, but hopefully I will still be able to use it next halloween.
     

     
    The program is written in MPY (a simplified variant of Python), and the syntax should be easy enough to understand.

    ###################################################################### # # ghost_screamer.mpy # # ~~~~ Scary Halloween Ghost ~~~~ # Uses an Ultrasonic Detector on P1_5/P1_4 to detect # presence of passing trick-or-treaters. When detected # it flashes LED (P1_0) randomly, makes a whooooh sound and # sends a pulse to the Tx module # The ultrasonic detector produces a variable width # pulse (ECHO on P1_5) whose pulse width is proportional # to the distance. Pulses that are too long or to short # are ignored as these a false triggers. This was done # as the ultrasonic detector HC-SR04 is prone to produce # rogue pulses. # ( Mike Asker 18-Sep-2013 www.mpyprojects.com) # ###################################################################### TRIG = P1_4 ECHO = P1_5 TX = P1_3 SPKR = P1_6 LED = P1_0 ###################################################################### def timer(): '''Define a timer function. This will be run every 6ms as a watchdog timer interrupt This will handle any things we want to do in the background. Like sending TX data and flashing the LED''' global tcount global r tcount += 1 # Toggle the data signal to the TX module # (I think it needs to be kept modulated for the RX receiver to work. # Change the TX pulse form 1ms to 2ms if we want to send a '1' (this is a very # low rate signal!) This is being done once every timer tick (6ms) out(TX,1) if enable_tx > 0: wait(2) else: wait(1) out(TX,0) # Flash the LED if tcount % 10 == 0: tcount = 0 # If the volume is turned on, (ie we have detection) # flash the Led in a random manner r = random(r) if r > 10000 and volume > 0: out(LED,1) else: out(LED,0) #################################################################### # Main program starts here #################################################################### # Setup the pin directions pindir(LED,OUT) pindir(SPKR,PULSEOUT) pindir(TRIG,OUT) pindir(ECHO,IN) pindir(TX,OUT) volume = 10 tone = 900 tcount = 0 volume_inc = 1 tone_inc = 5 interrupt_setup( WATCHDOG_TIMER, WDT_ADLY_1_9, timer) # setup an interval timer 6ms eint() # start the interupt timer running pulse_enable(0) # enable the timer0 used for the speaker # Enter a continuous loop while 1: # Output a trigger pulse to start the ultrasonic detector out(TRIG,1) wait_cycles(50) out(TRIG,0) # Wait a millisecond before we start to look for the echo # this gives enough time for the ECHO signal to go high # at the start of the pulse wait(1) ecount=0 echo = 0 # While the ECHO signal is high loop round once every 10us # and increment ecount. Break out of the loop when echo # goes low, the value of ecount will be the pulse width # (units of 10us) while ecount < 200: if echo == 0 and inp(ECHO) == 0: echo = ecount ecount += 1 wait_cycles(10) # If the width is within the narrow range of 400us - 600us # then we have detected a trick-or-treater if echo > 40 and echo < 60: # Send a '1' to the RF module enable_tx = 1 # Make a whoooh sound! tone = 900 # Set an initial tone frequency value tone_inc = 10 # Start with an initial +ve tone increment for i in range(5): # Repeat the whoooh 5 times for j in range(20): # Increment the tone frequency to make the spooky whooo sound # but only within narrow limits. When it hits a limit change # the direction of the increment, so the tone will go up and then # down tone += tone_inc if tone > 1100 or tone < 800: # if the tone hits the limits invert the increment tone_inc = -tone_inc volume = tone/2 # Set max volume to max by making the width half the period pulse_period(0,tone) pulse_width(0,volume) wait(50) # update the tone once every 50ms enable_tx = 0 # Switch off the TX module after the first whooo # because we need to give only a short pulse to the RX module # otherwise it will keep running #switch off the speaker after we are finished with the whooo by setting the volume value to 0 volume = 0 pulse_width(0,volume) wait(100)  
    The Pully Motor Controller
     
    This is mounted onto a piece of hardwood attached to the house by the front door.
     

     
    It contains a pully driven by a 12v gear motor. I upped the voltage to 17v as I wanted more power from it!
    I used an old 17v laptop supply as it could supply plenty of current.
     
    The motor controller was a low cost L298N module I got from Aliexpress. This was able to handle the current and the higher operating voltage.
     
    I mounted a Launchpad board. Any of the normal DIL MSP430 chips can be used as the code only takes 1800 bytes of flash.
     
    There are two pushbutton switches to allow the motor to be manually controlled while I was working on it.
    There are two infrared detectors to detect when the ghost has reached the end of its travel, both to the left and to the right. I got the infrared detectors from buildsmarterrobots.com, but I don't think he is selling them anymore.(other detectors can be used instead).
     
    The circuit uses a 3.3v regulator for the Launchpad MSP430 supply and for the infrared detectors. I needed to add a 33ohm power resistor to this regulator to reduce the power the regulator was dissipating as the drop from17v to 3.3v together with the rather large current taken by the infrared detectors meant the poor regulator was getting too hot. By adding this resistor it reduced the voltage drop across the regulator, and so lowering its power dissipation.  The L298N motor controller and the RF Receiver use a 5v supply, I used a 5.1v zener diode for this supply (I would of used a 5v regulator, if I had one)
     

     
    Here's the MPY code for the ghost pully controller
     
    ###################################################################### # # ghost_chaser.mpy # # Program to move a ghost along a line # ( Mike Asker 18-Sep-2013 www.mpyprojects.com) # ###################################################################### SWLEFT = P2_7 SWRIGHT = P2_6 MOTOR_A1IN = P1_0 # also the Red LED >> MOTOR RIGHT MOTOR_A2IN = P1_6 # also the Green LED >> MOTOR LEFT RX = P1_5 RXLED = P1_4 IRLED = P1_2 IRTOP = P1_7 IRBOT = P1_3 STOP = 3 LEFT = 1 RIGHT = 2 MIDDLE = 0 ######################################### def left(): global motor out( MOTOR_A1IN, 1) out( MOTOR_A2IN, 0) motor = LEFT out(IRLED, 1) ######################################### def right(): global motor out( MOTOR_A1IN, 0) out( MOTOR_A2IN, 1) motor = RIGHT out(IRLED, 1) ########################################## def stop(): global motor out( MOTOR_A1IN, 0) out( MOTOR_A2IN, 0) motor = STOP out(IRLED, 0) ########################################## def ghost_dance(): '''Pull the ghost back and forth a few times and then pull it all the way to the door (right) wait a while and then pull it all the way back to the front gate (left)''' global position position = MIDDLE wait(5000) right() wait(1000) for i in range(3): left() wait(300) right() wait(300) stop(); wait(2000) right(); wait(3000) stop(); wait(5000) left() while position == MIDDLE: if motor == LEFT and inp(IRTOP) == 0: stop() position = LEFT wait(5000) stop() ############################################################# ## Main program starts here ## ############################################################# # Set the pin direction of all the IO pins pindir(IRLED, OUT) pindir(IRTOP, IN) pindir(IRBOT, IN) pindir(SWLEFT, INPU) pindir(SWRIGHT, INPU) pindir(S2, INPU) pindir(MOTOR_A1IN, OUT) pindir(MOTOR_A2IN, OUT) pindir(RX, IN) pindir(RXLED, OUT) out(RXLED, 0) position = MIDDLE out(IRLED, 0) stop() print( 'prog started' ) rx_count = 0 lcount = 0 c0 = 0 c1 = 0 rx = 0 rx_prev = 0 detect = 0 wait(3000) # leave some time to allow the supplies to settle. while 1: # If the ghost is moving out (left) and the top ir sensor is activated # then we've hit the endstop, swtich off the motor if motor == LEFT and (inp(IRTOP) == 0 or inp(IRBOT) == 0) and inp(SWLEFT) == 1: stop() position = LEFT # If the ghost is moving inwards (right) and the bottom ir sensor is activated # then we've hit the endstop, swtich off the motor if motor == RIGHT and (inp(IRBOT) == 0 or inp(IRTOP) == 0 ) and inp(SWRIGHT) == 1: stop() position = RIGHT # Make the ghost run under button control if inp(SWRIGHT) == 0: right() position = MIDDLE else: if inp(SWLEFT) == 0: left() position = MIDDLE # Stop the motor if the opposite button is pressed while # while running if inp(SWRIGHT) == 0 and motor == LEFT: stop() wait(1000) if inp(SWLEFT) == 0 and motor == RIGHT: stop() wait(1000) # Look for an RX signal from the Ghost which indicates that the # tick-or-treater has been detected. If detected then make # the ghost do a little dance rx = inp(RX) c0 = 0 c1 = 0 # First make sure the motor is already stopped, # then if the we have a falling edge on the RX signal # count how long it stays low (c0), # and then count how long it stays high (c1) if motor == STOP and rx_prev == 1 and rx == 0: while inp(RX) == 0: c0 += 1 while inp(RX) == 1: c1 += 1 out(RXLED,0) # Save the c1 high count, and if it is the within the correct limits # then we have a '1' and we have detected the trick-or-treater, lets dance! rx_count = c1 if rx_count > 150 and rx_count < 220: detect = 1 out(RXLED, 1) # switch on the detection LED ghost_dance() else: detect = 0 out(RXLED, 0) lcount += 1 rx_prev = rx
  10. Like
    GeekDoc reacted to Fred in Suggestions/Thoughts on a donation button   
    I'm all for donations to support the site. I get a lot out of it and would be happy to contribute. However, I don't really need anything from the store and I know that international shipping makes it more hassle for Bluehash than it's worth.
  11. Like
    GeekDoc reacted to rockets4kids in Suggestions/Thoughts on a donation button   
    My suggestion would be to price items from the store more appropriately and use profits from the store to support the site.
     
    I have recently gotten in to R/C, and one of the sites most rapidly growing in popularity is flitetest.com.  While I personally consider their products to be insanely overpriced, they have had such such great response that they have actually had to hire additional employees to fulfill all of their orders.
  12. Like
    GeekDoc reacted to RobG in Ethernet Booster Pack v3   
    Buy: The 43oh Store or Rob's Tindie Store.
     
    The newest version of the Ethernet BoosterPack is based on the newest chip from WIZnet, W5500.
     
    P1.5 - SCLK
    P1.6 - MISO
    P1.7 - MOSI
    P2.3 - /CS
    P2.4 - /INT
    P2.5 - /RST
     

     
    Configuration jumpers are on the bottom, PMODE1-PMODE3, LINK LED, and ACT LED.
    LED jumpers control which LEDs are used, on board or socket.

     
     
    Available on Tindie.
  13. Like
    GeekDoc reacted to Fred in Adjustable MSP430F5529 Launchpad enclosure   
    I'm working on a project that should end up with a nice etched F5529 board, but for now it's going to just have a Launchpad stuck in there, I needed a quick enclosure for it so knocked up an adjustable one in OpenSCAD. I know a few people have (or are thinking about) a 3D printer so thought I'd share. It allows you to adjust the space on any side of the LaunchPad for anything else you want to include. It could do with some improvements - e.g the little locating pins are easy to snap off. Feel free to amend if the SCAD file if the available adjustments don't suit you.
     

     
    Here's a photo of it, with the partly-finished project in the background and the printer busy printing the lid...

  14. Like
    GeekDoc reacted to Fred in Adjustable MSP430F5529 Launchpad enclosure   
    F5529LaunchPad case.scad.txt
    I thought I'd attached the SCAD file (as text) but will try again. 
  15. Like
    GeekDoc reacted to Fred in Adjustable MSP430F5529 Launchpad enclosure   
    F5529LaunchPad case lower 43oh.stl.txtF5529LaunchPad case upper 43oh.stl.txt
    ... and STL files (with .txt extension that needs to be removed.)
  16. Like
    GeekDoc reacted to semicolo in Build thread - 3 Axis pen plotter   
    I'm finishing putting together my first 3d printer and attached a pen to make a test: http://youtu.be/t81QYGiyXX4
  17. Like
    GeekDoc reacted to tripwire in TI releasing something "game changing" on Sept 16th   
    Hang on... A $30 detector for electronic components dropped on the carpet? Now that really *is* game changing!
  18. Like
    GeekDoc reacted to abecedarian in Is it just me or tonight TI doubled LaunchPad price?   
    One I ordered Sept. 18 shipped Oct. 3. A two week lead time isn't bad. Could be worse- it's taken longer for things I've ordered off e-bay to ship.
     
    I should've ordered some of the protoboards from the 43oh store when they were on sale. :-(
     
     
    *edit- It arrived today, Oct 7, via Fed-Ex. Shipped on a Thursday, arrived the following Monday.
    The backorder status it had said it would ship in November so I can't complain.
  19. Like
    GeekDoc reacted to Rickta59 in Is it just me or tonight TI doubled LaunchPad price?   
    OK, so I've been using the new msp430f5529 launchpad for a week or so. It seems like TI listened to our concerns. They have addressed most of the issues I have with the previous msp430 launchpad offering.
     
    o ) Serial issues , resolved, new version includes a small on board USB hub that provides a direct connection for the FET and one for the user USB. It runs faster than 9600 and doesn't seem to cause linux to hiccup.
     
    o ) Small ram and flash size. The msp430f5529 has 8k of ram and 128k of flash. In addition, the chip has been around for a while so you can order them from regular distro channels
     
    o ) Linux CCS full support. This LP has the ezFET device and it fully supports debugging using CCS with linux. Also, the open source tilib (libmsp430.so) works great with mspdebug and provides hardware debugging features only previously available with the "real" FET. Finally, the firmware can be upgraded so it can be used with newer chips that appear on the scene.
     
    So hats off to the TI crew, this launchpad seems worth the price they are asking !
     
    -rick
  20. Like
    GeekDoc reacted to cde in Elecrow PCB Service - Free color   
    HK government shutdown. If the US shuts down, everybody else has to or look like untrendy losers. /sarcasm.
  21. Like
    GeekDoc reacted to zeke in My first fried MCU   
    Do you have any local friends who have a soldering iron that you like?
     
    Maybe you could visit them and test drive their soldering iron for a little bit?
    Maybe you could talk with them about your blown arduino at the same time?
     
    I bet that they would be a great encouragement to you!
  22. Like
    GeekDoc got a reaction from PedroDaGr8 in Noritake Graphic VFD 128x32 Free Sample   
    Just got mine. I haven't hooked it up yet but, to appease @@abecedarian :

  23. Like
    GeekDoc reacted to spirilis in Powering the MSP430 on Launchpad w/Emulator Disconnected   
    So the reason this happens, is that the RESET and TEST (and RXD, TXD) lines connect through those jumpers to other MCUs that are part of the Emulation layer.
     
    If that emulation layer is not powered, i.e. you applied power to the Vcc + GND lines of the target but the USB cable is unplugged, then the emulation-layer IC chips will have a 0V potential on their Vcc lines and seeing a higher-than-0V level on some of their GPIOs (the ones that ultimately lead to your RXD, TXD, TEST, RESET pins in your target) will cause power to flow through the "protection diodes" on the emulation ICs.
     
    Your target, in effect, is powering the emulation layer through any means possible ... the RESET pin probably being the only one that has a consistent +Vcc voltage level on it.  But since the only Vcc power applied to RESET is through a fairly high-value resistor, it doesn't take much load to drop that voltage very low to the point that it holds your target in RESET mode.
  24. Like
    GeekDoc got a reaction from abecedarian in Noritake Graphic VFD 128x32 Free Sample   
    Just got mine. I haven't hooked it up yet but, to appease @@abecedarian :

  25. Like
    GeekDoc got a reaction from bluehash in Noritake Graphic VFD 128x32 Free Sample   
    Just got mine. I haven't hooked it up yet but, to appease @@abecedarian :

×
×
  • Create New...