Showing posts with label Arduino. Show all posts
Showing posts with label Arduino. Show all posts

Wednesday, June 3, 2015

Esp8266 - Project Progress

For the last several weeks I have been programming my Esp8266's, I have experienced frustration, anguish, and some delight.

The frustration comes from the fact that the Esp8266 is a relatively new product and not all (or enough) documentation has been translated from Chinese to English. Or, the six or so, development environments (i.e. IDE's) are implementing conflicting strategies for supporting libraries and functions. Sorting out what is relevant, is sometimes difficult

So far, I have been using the Arduino IDE (originally Rev 1.6.1) which support the Esp8266. The included Examples are nice, but are not very useful as for an actual application, that is, they do not suggest how to implement typical combined solutions for some rudimentary functions.

For example, I think a typical home-grown project should have the ability to run in Software Access Point (SoftAP) mode at initial turn-on and accept configuration or connection information for Station (STN) mode connecting to local Access Point (AP) for further operations.

My Goal

My goal is to build that function into my project, but the details lacking on how to switch from one Channel or SSID to another via software control. The Esp8266 can be easily "Programmed" to attach to a selected AP, but that requires a new download for each environment. I am sure the solution is simple, but so far it eludes me.

Still Learning

I have learned a lot, and I have many of my desired functions working.

Note: two things I have learned about the Arduino IDE that I did NOT know, and documented here for my future reference, are;
  • First, Arduino IDE Tab Sections (normally files) with a hidden ".ino" suffix are compiled as part of the "main" file ("*.ino") without the need for the usual compiler "forward" declaration and "export" declarations typically found in other software IDE's. This is very handy for quick small projects, where organization is more important than software development correctness.
  • Second, Arduino IDE "control /" will convert a section of code into a "comment" and back again. This is very useful while debugging. This short-cut has always been there (I guess) but I had not previously used it, but now I use it all the time.
Project Template

In general, I am creating a "template" for my future projects. The template will have the following functions:
  • A "Dashboard" page which is accessible via the assigned device IP Address or alias.
  • A "Help" page that will list all of the available functions
  • "Query" methods or functions to extract data, that can be used via a web page or non-typical web access methods (e.g., curl, telnet, etc).
  • An "Admin" page, to control different aspects of the device.
  • A "Navigator Bar" to switch between pages and "Links" to support information.
  • A mDNS Responder, so that a device can be access via a "*.local" alias.
  • My goal is to include MQTT functions

Here are some example Pages, The Navigator Bar can be used to switch pages. Note: code was included to make the pages, Desktop and Mobile Device Friendly:
Home Page - The Dashboard
This is the "Admin Page" after a WiFi Scan, network selection and Passphrase can be entered to switch networks.
Admin Page - WiFi Scan
 The Help Page provides information and links.

Help Page
Note: the Help page provides links and/or URL's so that a "Query" can easily be constructed for Raw Data access. For example, on a remote system:

$ curl Nod1590.local/q/uptime 

The above will prints just the number of seconds (uptime) since power-on.

Some Hurtles

One of the most troublesome aspects of my Esp8266 development was dealing with unexpected web request. Initially, my tests were simple and successful, I was using a Firefox browser on my LinuxMint Workstation, where a simple single web requests received a simple single response from the Esp8266 App. The app provides a "404 Error" for all unexpected web request. This all worked great, and as expected.

But Then . . .

But then, I tried my app using my Cell Phone and Tablet Browsers, which quickly crashed my Esp8266 Web Application. The problem was these browsers repeatedly (and relentlessly) request a "/favicon.ico" file, which over-ran the Esp8266 buffers, or just "hogged" all of the available bandwidth ( which I have very little, I have a slow and terribly BAD Internet connection to my Shop ). The "/favicon.icon" requests can NOT be "ignored", they just keep coming and therefore the Esp8266 must deal with them. I spent several days (actually more than a few) looking for a solution, including creating and sending a dummy ( or contrived ) files to satisfy the requests. The online searches provided many suggestions, but in all cases the solutions were not optimal, they all still uses my (scarce) network bandwidth and small Esp8266 buffer space.

My devised and final solution was much more simple than I expected (and elegant, if I may say so). I pre-emptively re-direct all external "/favicon.ico" requests to where they belong - that is, to Espressif (the Manufacture) web site where they happily (or at least hopefully so) provide the file. The redirection takes place in the Browser and therefore the data transfer is between the browser and manufacture, and NOT with my Esp application. Espressif gets the web hits and I get bandwidth relief, the user sees a nice icon on the Exp8266 App browser tab, and my application does not have to deal with the issue. A single line in the Esp's web application html Header does the trick. Very-Very Simple!



<link rel="shortcut icon" href="http://espressif.com/favicon.ico"></link>



Note: Yes, I know this solution may not be web polite, and if I find a better solution, I will post it.

Lack of Understanding

Another thing that plagued my early Esp8266 App development was my lack of understanding of the "Strings Objects"! I have been working with too many languages lately. My friend Jeff - KO7M has helped and provided suggestion. In general, I was originally inappropriately using Strings that could be trashed (and crashed) by the "Garbage Collection" (GC) process. Most web page generation is about generating Large strings, managing them is important so that the "Heap" is not stressed and so GC can properly reclaim space.

But Now, Progress

Also, to save RAM space, I am using a previously used technique (see previous post) of moving all "string constants" to FLASH using PROGMEM, and "not" using the Heap, and there by avoiding some of the RAM space issues. As stated above, most web pages generation is just manipulating long strings in RAM.

To Be Done

I just have a few more issues to work out, and then I will publish the code as an example of Stand-alone Esp8266 Development App.


-- Home Page: https://WA0UWH.blogspot.com

Thursday, October 16, 2014

Minima - Encoder, Two Implementions

After several days of work, I think I now have a working set of Encoder Routines that are usable for the Minima. Testing has been done by several builders.

The first routine: Encoder01, uses a polling analog read (non interrupt) to detect the Encoder switch changes and is not listed below.

The second routine; Encoder02, is usable for the builders that have moved to an I2C LCD and therefore have two dedicated microprocessor pins to connect to the Encoder pins A and B.

The third routine; Encoder03, is usable for builders that continue to use the parallel LCD and therefore do NOT have dedicated pins to connect to the Encoder. The previous Analog Tuning Pin and the FN Pin are used as shown in the suggested multi-switch schematic.

Selecting which Encoder routines are used, is done via a Optional Configuration selection in the "A1Config.h" file, by un-commenting the selected Encoder.



//#define USE_POT_KNOB  1 // 2304b - Option to include POT support
//#define USE_ENCODER01 1 // 2220b - Option to include Simple Encoder01 support
//#define USE_ENCODER02 1 // 2610b - Option to include FULL Two Digital Pin ISR Encoder02 support
  #define USE_ENCODER03 1 // 2604b - Option to include ISR Encoder03 support On Tuning Pin


Now that the details are work out, the Encoder supporting routines are short and simple. Each containing the "tigger" debounce timers as suggested by the author of the PinChange Library. Yes, it is called "tigger", because everyone knows tiggers bounce, as in Winnie-the-Pooh.

Some unnecessary detail are left out of these listing, check the GitHub for the actual code.

For Encoder02, these routines are used:



#include "PinChangeInt.h"

volatile int knob;

// ###############################################################################
void encoderISR() {
    int pin = ENC_B_PIN;
    static unsigned long startTime = 0;
    unsigned long tigermillis;
    uint8_t oldSREG = SREG;

    cli();
    tigermillis = millis();
    SREG = oldSREG; 
    if (tigermillis-startTime <= ISR_DEBOUNCE_TIMEOUT) return;
    startTime=tigermillis;
    
    knob += digitalRead(ENC_B_PIN) ? -1 : +1;
}

// ###############################################################################
void initEncoder() {
    int pin = ENC_A_PIN;
     
    pinMode(ENC_A_PIN, INPUT_PULLUP);
    pinMode(ENC_B_PIN, INPUT_PULLUP);
    
    PCintPort::attachInterrupt(pin, &encoderISR, FALLING);
}

// ###############################################################################
int getEncoderDir() {
    char tmp = knob;
      
    if (tmp>0) {uint8_t oldSREG = SREG; cli(); knob--; SREG = oldSREG; return +1;}      
    if (tmp<0) {uint8_t oldSREG = SREG; cli(); knob++; SREG = oldSREG; return -1;}
    return 0;
}


For Encoder03, these routines are used:



#include "PinChangeInt.h"

volatile char knob;

// ###############################################################################
void encoderISR() {
    int pin = ENC_B_PIN;

    static unsigned long startTime = 0;
    unsigned long tigermillis;  
    uint8_t oldSREG = SREG;

    cli();
    tigermillis = millis();
    SREG = oldSREG;   
    if (tigermillis-startTime <= ISR_DEBOUNCE_TIMEOUT) return;
    startTime=tigermillis;
        
    knob += analogRead(pin) < 440 ? -1 : +1;
}

// ###############################################################################
void initEncoder() {
    int pin = ENC_A_PIN;
      
    pinMode(ENC_A_PIN, INPUT_PULLUP);

    PCintPort::attachInterrupt(pin, &encoderISR, FALLING);
}

// ###############################################################################
int getEncoderDir() {
    char tmp = knob;

    if (tmp>0) {uint8_t oldSREG = SREG; cli(); knob--; SREG = oldSREG; return +1;}
    if (tmp<0) {uint8_t oldSREG = SREG; cli(); knob++; SREG = oldSREG; return -1;}
    return 0;
}


Notice: Only a few lines are different between the two implementations.


-- Home Page: https://WA0UWH.blogspot.com

Saturday, August 2, 2014

Minima - Very Little Progress

The lack of posting on my part does not mean that I have not be very actively working on my Minima Controller.

I received from OSHPark.com the replacement boards for my damaged Minimal Controller. I loaded the board with as few components as necessary to install the bootloader and verify the microprocessor's operation.

That is were I have been STUCK for the last few days.

The "out of the box" ATMEGA328P-MU does not contain a bootloader and does not appear to be able to converse with my USBTinyISP for installing the bootloader.

The Original Board with
Microprocessor and Crystal
The "-MU" version for the microprocessor solders directly to the PCB, along with its attending (and very small) crystal. The processor works or it doesn't, trouble shooting is very difficult because each can NOT be easily replaced with known good parts, and a short under the part means it removal just for the inspection.

For the new board, I have replaced each part with "package fresh" parts, but with the same results. If I had used the much larger DIP version of the microprocessor, this would have been a no-brainer repair. The DIP version would have been removed and then place into an Arduino-UNO and programmed as per the documentation.

But I still like the challenge of using the very smallest parts that are available, and this has been a challenge.

My original Minima Controller exhibited a similar "brain dead" behaviour when I first turned it ON. But while stumbling around trying different things, it some how got into the correct state and accepted the bootloader. I do not know or understand the events that lead to success.

The ATMEGA328 has what are called "fuses" to configure its operational states. These fuses once set, stay set, and affects further operation. One of the fuses configurers the Clock, which is necessary to run at 16MHz from the crystal, otherwise the Clock runs at a much slower speed via an internal RC clock.  I suspect that my new microprocessors are running a the slow speed and therefore unable to accept my bootloader from the Arduino IDE.
 
The previous board was damage, but with the aid of the microscope and some very intense micro soldering, I think I have repaired the damage. But alas, the newly installed replacement processor is behaving exactly as that of the new board (at least the two board are consistent). I just need to find the "Magic" that will allow them to accept the bootloader.

Jeff - KO7M, has been providing suggestions to help with my problem. So far nothing has worked.

Once the bootloader is accepted, programming the Minima Controller via the Arduino IDE is a breeze.

Hopefully, good news will follow.

--

Sunday, July 6, 2014

Minima - Alternate Tuning Method - Cont'd

I have been working on Software for the Minima Transceiver. As posted before, my plan was to provide an Alternate Tuning Method for the Minima.

 In the Beginning

The original tuning method was provided via a standard POT that had a center position that did not change the frequency of the radio. When turned off center to the left the frequency would go down in different steps depending on how far from center the POT was turned. Once near the desired frequency, turning the POT back toward the center would decrease the steps size so that tuning could be stopped on the desired frequency. The same is necessary to increase the frequency, but in the opposite direction. The original Driver for the Si570 did not have 1Hz resolution and therefore the preprogrammed tuning steps was a reasonable, or an acceptable solution.

New Direction

I desired higher resolution and a more natural way of tuning the Minima Transceiver, within the limits of using the existing Minima hardware as much as possible. And I wanted to add some additional features to the software, see below. A method of adding additional push buttons switches was found, thanks to Minima e-mail contributors.The button circuit can be found here. Note: most of the wiring can be done on the front panel, next to the switches.

With a lot of work Jeff - KO7M, rewrote the Si570 Driver to provide better than 1Hz resolution. He did so by, rewriting the original floating point algorithms using fast 64bit interger math. His Driver is a plug-and-play replacement for the original. Jeff's Si570 Driver can be found here.

Writing replacement software to implement my Alternate Tuning Method started as a simple modification and grew into a major rewrite of the Minima program sketch. Many people around the world provided inspiration, testing, and ideas that were eventually included in what it has become today.  

Jeff - KO7M, Wayne - NB6M, and John - MI0DFG are major contributors.

The functionality of this program will continue to grow; to include menus, beacon modes and several other interesting ideas. Programming space is limited, but some things can be carefully added.

But, Program Modifications and Additions have Costs

One major cost, hassle, or headache was how to minimize the use of Variable Space to stay within the 1K bytes (RAM) available on the ATMEGA328P microprocessor.

So far, the Program Space has not been an issue, currently the program uses only about 20K bytes of the available 32K bytes (FLASH).

Free Memory from the Variable Space (RAM) is necessary for proper program execuiton as the "stack" used by each programmed function consumes and releases it as they are called. There are NO reported run-time errors if ALL of the Free space is used, the program just become erratic or fails (crashes). Using ALL of Free Memory is NOT a good thing. At one point, there were only 322 bytes of available Free Space at program reboot (way too little), program crash was inevitable.

An analyses of Variable Space of the modified Sketch indicate that most of it was used by String Constants within the program. A method was needed to move the String Constants to FLASH Memory, and out of RAM. With lots of research and putting disconnected ideas together, a method was concocted that provided the solution. The problem is discussed, but no-where on the web could I find a suggested cut-n-paste integrated solution.

Arduino String Constant Moved to FLASH Memory

The solution that I came up with is implemented via a set of Macros. The macros uses the PSTR construct in conjunction with a "strcpy_P" function. My simple solution is implemented as a buffer and two simple macro. This solution is not as fast as it could be, because it copies the String Constants back to RAM before it's used. But in doing so, the String Constants can be used anywhere within the program as normal, by wrapping it in a simple "FLASH( ... )" programming construct.



char buf[60];
// ERB - Force format stings into FLASH Memory
#define FLASH(x) strcpy_P(buf, PSTR(x))
// FLASH2 can be used where Two small (1/2 size) Buffers are needed.
#define FLASH2(x) strcpy_P(buf + sizeof(buf)/2, PSTR(x))


A few examples from the Minima Sketch as used:



debug(FLASH("Register[%i] = %02x"), i, dco_reg[i]);

sprintf(c, FLASH("%-16.16s"), FLASH2("VFO swap!"));
printLine2(c);



These examples are saved here for my future reference, and hopefully saved where other programmers may find it, and find it as useful.

After moving the String Constants to FLASH Memory, it has grown from 20K to about 21.5K bytes, but still with lots of room for careful additions.

This solution has changed Free Memory from 322 bytes to 1070 bytes for this Minima Program Sketch. With 1070 bytes of Free Space the program will not (should not) fail for lack of stack resources.

The Alternate Tuning Method

The Alternate Tuning Method implements the following, which are not found in the original sketch.

  • High resolution, plus/minus 1Hz Tuning (thanks to Jeff).
  • Near Normal Dial Tuning as found on most Dial Radio system.
  • Tuning Cursor positioning via Left/Right push buttons
  • Automatic (original) or Manual Selection of Sideband via push button
  • Nine Ham Band Memories, with Frequency and Sideband Save via Up and Down push buttons
  • RF386 Power Amplifier Filter Selection via generated clock pulses (Note: Not a lot of testing has been done on this yet)

Thanks to the people on the web and Minima e-mail list, the current Alternate Minima Tuning software is working very smooth and provides some very desirable functions.

The GitHub Repository where this software is available, is:


As the software continues to be developed, the GitHub Repository will be updated, check back often.

A complete dynamic list of my Minima Project posts are available via this search link (which will include this post):




UPDATE: July 14, 2014 12:16
After much more research, I found the use of "PSTR" used in a similar context as I have suggested documented, at:

http://electronics4dogs.blogspot.com/2010/12/simple-way-how-to-use-progmem.html

I wished I have found this link long ago.


--

Tuesday, June 10, 2014

Minima - Multiple FN Buttons

At the request of John - MI0DFG, I have been rewriting my Alternate Mimima Tuning Method.

John suggested that moving the cursor via (additional) buttons would work much better than waiting for the cursor mode to automatically switch intervals as I proposed.

The problem is the original Farhan's Minima does not have extra pins available for dedicated connections for additional switches. John suggested maybe we abandon pins 2 and 3, because he has an alternate method of programming his Arduino. I checked the possibilities and it could be done at the expense of Arduino Bootloader use, and at the expense of the programmer DEBUG output. Nether of which I would like to abandon.

But

An alternate method was suggested by someone (?) on the Minima Reflector, more User Buttons can be provided by a network of Resistors and Switches on an analog pin.

The current FN Switch is on an analog pin, and switches (and resistors) can be added in parallel.

Currently

I have successfully added six additional Switches in parallel to the original FN switch, and have written a Sketch Modification to decode them.

I was able to retain the original FN button's definition; Momentary, Double Push, and Long Push.

The first two new switches will be used to move the cursor; "Left" and "Right".

Current the other four switches are currently being defined as the Sketch is being changed.

This new (and preliminary) User Interface (UI) works very natural and smoothly with my new Sketch. I will soon publish the NEW Sketch that I used to decode these switches (unfortunately, I currently have another major project that is interfering with this Hobby project).



The following circuit should be added to implement multiple switches parallel
to the original FN Switch.

--------+
Arduino |
        |
    AVCC|--------+---1K---- +5V
        |        |
        |        = 100nF
        |        |
        |        v
        |
    AREF|----+-------+
        |    |       |
        |   47K      = 100nF
        |    |       |
        |    |       v
        |    |
   pin26|----+-----4K7---+---4K7---+---4K7---+---4K7---+---4K7---+---4K7---+
        |    |           |         |         |         |         |         |
        |   FNS          S         S         S         S         S         S
        |    |           |         |         |         |         |         |
    AGND|----+-----------+---------+---------+---------+---------+---------+
        |    |
--------+    v

            "FN"       "Left"   "Right"   "SBand"     "Up"     "Down"     btn7
           (btn1)      (btn2)    (btn3)   (btn4)     (btn5)    (btn6)    (btn7)


Where:
  4K7 is a 4.7K ohm resistor
  47K is a 47K ohm resistor
  FNS is the original FN switch
    S is a new switch
    = is a capacitor
    v is a ground and AGND

  AVCC is:
     pin 20 on ATMEGA328P-PU, check spec sheet for other packages
     
  AREF is:
     pin 21 on ATMEGA328P-PU, check spec sheet for other packages

  AGND is:
     pin 22 on ATMEGA328P-PU, check spec sheet for other packages

Note: The use of AVCC, AREF, and AGND with these analog circuits ensure consistance
      decoded values for use within the Sketch.

Note: To avoid ground loops, the ground sides of all Switches should be
      connected to the same point on the FN Switch and AGND.

Note: Not all switches and resistors are necessary, install only
      the left most desired switches and resistors, the current software
      only decodes seven switches total.

When used with my Alternate Tuning Method Sketch:
      "Left" and "Right" buttons moves the Cursor
      "SBand" selects the Side Band Mode; "Auto SB", "USB", or "LSB".
      "Up" and "Down" switches Ham Band, and saves the current

--


Note: this information is preliminary, and applicable to only the most adventurous Minima builders.

See a suggested Button Grouping at:




UPDATE: Jul 2, 2014 12:33
The GitHub that contains the Preliminary Sketch that supports the above is at:



--

Sunday, June 1, 2014

Minima - Proposed New Tuning Method

This post is for a few brave (adventuresome) Minima builders/users. This is a "work in progress" and therefore feedback is requested.

Although I have not completed my experimental Minima Transceiver build, I have built the Digital Control Module and have been working on the Arduino software that controls the Display and the rest of the Minima hardware. See my previous blog posts, or at:

Minima Digital Control and VFO Module
Running REV 0.4.erb
One of the modification that I have made is to incorporate Jeff's (KO7M) 1Hz Driver for the Si570. This modification allows for 1Hz Tuning of the my Minima's VFO. Jeff's Si570 code is available on GIT Hub at:


Also, I have been working to modify the Arduino Sketch to provide an Alternate Tuning Method, what I consider a "Near-Normal" tuning method or functionality, for the original Farhan's Minima circuit and hardware. With only the original circuit's tuning POT to work with, functionality is of course somewhat limited.

The original Minima Arduino Sketch (REV 0.4) changes frequency via the Tuning Pot and pre-programmed steps. Tuning rate is dependent on how far from the "center of rotation" the Tuning Pot is turned. To tune "up and down" around a received signal the Tuning Pot must be turned past the Pot's center location, which of course is not typical of a normal receiver. Farhan's original Minima Arduino Sketch (REV 0.4) is available at:


The original Minima Arduino Sketch of VERY functional. But, I as programmer, and like they say: "programmers will be programmers, and they will modify programs", so, I am, what I am  :-)

My goal for this program modification is to maintain the functionality of the original Minima Arduino Sketch and incorporated Jeff's Integer Si570 Driver, which provides High Resolution Tuning (< 1Hz).

My modified Sketch, can replace the original Minima Sketch (REV 0.4) via a normal Arduino IDE compile and download. And if needed, the original Sketch can be re-installed via the same method.

This modified Minima Sketch (REV 0.4.erb) is available on my GIT Hub, at:


This revision ALSO provides the following:
  • This Sketch can be used in place of original Minima REV 0.4 Sketch (but of course, use at your own risk).
  • Provides Eight Digits for Frequency Display
  • Provides 1Hz Tuning Resolution

     Provides a Near-Normal Tuning Method
  • Tuning is accomplished by moving the cursor via the Tuning Pot to the digit that you want to change.
  • Then wait for the underline cursor to start flashing.
  • Then change the digit by turning the Pot left for lower, and right for higher frequency.
  • Near the Stops (the Pot rotational Stops) the digit will change automatically.
  • At the Stops, the digit automatically changes even faster.

After you stop Tuning (i.e., stop changing the digit), the mode switches back to "cursor move mode" for a few seconds, as indicated by the Non-blinking Cursor, then repeats.
  • The cursor can be "parked" to the right of the least digit.

The current Mode is indicated by the cursor style:
  • Blinking Underline Cursor = Digit Change Mode
  • Non-Blinking Underline Cursor = Cursor Move Mode

These modes are ALSO indicated by the far right character on the top line:
  • "*" = Cursor Move Mode
  • "-" = Digit Change Mode
  • "<" = Digit Changing to lower frequency
  • ">" = Digit Changing to hight frequency

Note: If the Cursor Move Mode seems to get lost, move the cursor to each of the two hard Stops to recalibrate cursor movement.

Some new functions on my To-Do list include:
  • Stay Compatable with Original Minima Hardware
  • Provide for Rolling Menus
  • Band Pick from Menus
  • User Defined Frequency Memories
  • User Defined Frequency Tuning Steps (e.g. similar to FT-817's 2.5KHz steps)
  • Transmit Macro (send CW CQ, ID or more)
  • Transmit Mode from Menu
  • Beacon Modes: CW, QRSS, and WSPR-Tx
  • User Defined Operational Preferences; Digit Count, Tuning Rate, etc
  • etc

If you try this initial experimental "REV 0.4.erb", I hope you find it useful.


Have fun !!
and, Provide Feedback !!


UPDATE
Git Hub Repository URL's have been corrected.


--

Sunday, April 20, 2014

Minima - CPU Module Mods

While building my Minima CPU module, and thinking about the circuit's programming interface components. I started wondering if there was an Off-the-Shelf USB product that could replace and simplify the circuit.

After a little research, I found three likely candidates, all available from Parallax.com;


Each have slightly different header pin-outs for connection to a project. Each uses the same FT232RQ USB-to-Serial chip.

For DYI, the FT232RQ chip is a simple "state machine", which does all of the hard work of USB-to-Serial protocol and signal-level translation. It is simple enough that it could be included directly into a project, all that is necessary is; the FT232RQ, a USB connector, and a few resistors (see the Prop-Plug datasheet with schematic). Note: Parallax encourages use of their schematic for DYI implementation, they will be happy to supply the parts, or as available elsewhere.

If the FT232RQ is included directly in a project, the +5V from the USB connector could also be used by the project, only the off-the-shelf 4D Systems USB Programmer (listed above) provides a fifth pin for a power connection.

The FT232RQ is available in the 28-LD-SSOP and the QFN-32 package. I will use the QFN-32, because I like smaller components. The price of the FT232RQ is about $5.00, but that is cheap for what it does and the components that it replaces.

Also, if the FT232RQ is included directly as part of a project, it is available for generic ASCII I/O for control or output via a standard USB connection.

Because I already have a Prop-Plug, I think I will simplify and re-layout the next Revision of my Minima CPU module with a simple Prop-Plug header. I hope this will work as a generic dumb download interface with the Arduino Interactive Development Environmnet (IDE), but this remain to be tested. Does anyone know?


UPDATE: Apr 21, 2014 14:11
As per the comments, Larry has suggested the "FTDI Friend" - $15 from Adafruit.com

--

Sunday, November 3, 2013

Trinkets

OK, my parts were received from Adafruit.com, see previous post.

The USB Power Gauge works as expected, it is very handy to check the charge rate on my Cell Phone, and for checking power consumed by any USB device, including my Raspberry Pie and/or the BeagleBone computers. The USB Power Gauge provides information that is otherwise a little difficult to obtain.

I had also purchased three Adafruit Trinkets. I followed the recommended software (Ardunio IDE) install instruction, and modification needed for the Trinket. And then, I proceeded to "Brick" all three Trinkets (or at least that is what I thought). I have used the Ardunio Interactive Development Environment (IDE) many times in the past and was not expecting any problems.

Because the "Trinket" has only 512 Bytes EEPROM (boot loader ROM) part the loader (about 1.5K bytes) is placed in FLASH RAM, which leaves about 5.5K bytes for user programs.

While loading a user program into the remaining FLASH RAM, if something goes wrong, part of the boot loader can be overwritten, and therefore it is somewhat easy to "Brick" the Trinket.

Instructions are provide to "UnBrick" the Trinket, but that requires yet another Arduino and downloaded programs.

While reading many pages on the web trying to understand my problem, I discovered that for Linux machines may not support USB in the way that the Arduino IDE for the Trinket desires. The recommended method is to use a external USB Hub to connect the Trinket to a Linux computer.

It worked, . . . how or why, I do not know !!

The Trinkets were NOT actually Bricked, . . . they just looked and acted like it. While plugged into a Hub, they now respond as desired by the Arduino IDE.

My first task was, of course, to run "Blinky", the "Hello World" program.

Once that worked, I quickly put together the following CW sketch to send/blink "CQ" on the LED.


/*
  This Sketch Blinks CQ on the LED
*/
 
int led = 1; // blink 'digital' pin 1 - AKA the built in red LED

int WPM = 13; // Words Per Minute
int ditTime = 1200 / WPM;
int dahTime = ditTime * 3;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  delay(2000);

}

// the loop routine runs over and over again forever:
void loop() {

    for(int j = 0; j < 3; j++) {
      dah(); // C
      dit();
      dah();
      dit();
      eoc();
      
      dah(); // Q
      dah();
      dit();
      dah();
      eoc();
    }
    eow();
    
    delay(10000);
}


void eoc() { // End of Charactor
    delay(ditTime * 3); // added to previous End-of-Char time
}

void eow() { // End of Word
    delay(ditTime * 7); // added to previous End-of-Char time
}

void dit() {
    cwpulse(ditTime);
}

void dah() {
    cwpulse(dahTime);
}

void cwpulse(int duration) {
    digitalWrite(led, HIGH); 
    delay(duration);
    digitalWrite(led, LOW);
    delay(ditTime);
}


// End   

A more complete and non-trivial CW sketch would be table driven, but this was quick-n-dirty just to just get something to work.

More complex and interesting programs will hopefully follow.

I think the Trinket will have a place in my bag of tricks, for small Ham Radio Projects. I am currently thinking of maybe a Beacon Trinket Shield, and/or a Tennis Ball Launcher Trigger Controller.

--

Wednesday, December 7, 2011

Arduino IDE 1.0 Released

Arduino IDE 1.0 has been released (previous rev was known as 0023). The release notes provide insight into the new functionality. It will be interesting to see if I can use this new capabilities in my Ham Radio Projects.

To be compatible and consistent, Teensyduino, Version 1.06 was also released.

I have not downloaded either yet, as I am in the middle of a Multi-day Timing Test on my Teensy GUI Protoboard, but will download soon.

--

Monday, October 24, 2011

Teensy Programming Shield

Jeff - KO7M and I have been working on several Arduino and Teensy projects, to control QRP and Beacon Transmitters. To expand and progress to the point where we will use raw chips in planned projects we decided to produce a Teensy Programming (under) Shield. For several projects we have used the Teensy as the development platform.
As Designed in DipTrace

The Teensy will plug into the top of the Shield. After several iterations and corrections of schematic I we have a layout.

Today, I used the Toner Transfer Method to create the board. High resolution two sided boards are tough but they can be done. The Teensy Programming Shield is .75" x 1.75" with 8 mil traces.

Etched and Ready for Inspection
There are not many traces so it was not hard to route or build. If I had need for more than a few boards I would have sent it out for FAB.


The Etch Looks Good
and both sides look like they are in good alignment
These are 8 mil Traces, and 6 mil Ground Grid
After Laser Toner Resist is remove, the board is cleaned and polished, and then placed into a small dish of Tinnit. In about 5 minutes the board is bright and shiny.
Tinnit was used for Tin Plating
Tinnit works well, with good coverage,
but it is very thin (.004").
The Results:


Parts Loaded
Double sided HB board are difficult as the socket pin are typically used to transfer the traces between sides and therefore both sides of the socket pins require solder. With care this can be done by raising the socket a small amount and soldering with a very sharp iron. Also, small errors of alignment between the image of each side make for difficult drilling and therefore pad are not always centered on the component pins.

Cut, Drilled and Parts are loaded, in this case Headers and one jumper.

Ready to Use !
As you can see the Header were raised about 1/10" to facilitate top side soldering the few pads which are connected via traces. Raising the parts would not be necessary if this board was from a FAB shop, plated through holes would make loading parts much easier.

In use, the Teensy will cover the first 24 pins (far end), short jumpers will be used if need for the none standard Teensy pin locations. For ISP Programming effort, only one jumper will be required - the RST pin.

With the Teensy plugged in hopefully there will be enough space to plug in the programmers? To use the Shield to program the Teensy, a short jumper is still needed between the RST pin (on end of the Teensy) and the third pin on the near open socket holes. That hole, is connected to the RST pin on the 6 pin Programming Header. We could have included dedicated RST pin and socket as part of the Shield, but that would require we alter the Teensy with a dedicated pin, disallowing it to be used directly with simple circuits on protoboards.

The Teensy is Installed, Ready for Programming,
It can be used
In or Out of a Protoboard
Now it is time to do some Direct AVR Programming - Jeff!

--

Sunday, October 9, 2011

Teensy Test Jig Schmatic

Here is the Teensy Test Jig Schematic that I am using for the programs shown in previous posts.

Teensy Test Jig
Teensy  Test Jig Schematic
Rev: F
Teensy Test Jig - In Fritzing Format
Note: The Rotary Ecoders are show as "Trimmer Pots" with two extra pins at the top for the push button switch, the encoder part is not available in the Fritzing Library, I may need to create a custom part. I have updated the Fritzing diagram above - I had to build a custom Fritzing Rotary Encoder part.

I had to re upload the schematic, the first and second were flawed.

Note: The Photo, Schematic, and the Fritzing view are NOT all "exactly" the same.

This is a "work-in-progress" project.

--

Saturday, October 8, 2011

ISR Lessons Learned

If you follow my Blog, (see previous posts) you will know that I have been playing with an Arduino work-a-like known as the Teensy. The plan is use it to help make my Homebrew Projects smarter and maybe more interesting.

So far, I have been "playing" with it to build multi-tasking template for future projects. The first hurtle was to write a predicable Rotary Encoder Test routine. Which I have done and published on the previous post. Actually, the code that I published has been replaced three time as I learn more. Finally I think the code is solid and would not mind others to commit or post reviews.

It was a struggle getting to this point. I have several chats with my friend Jeff - KO7M, about several major issues that were . . . just kicking my butt. The program just did not operate the way I had in mind. But in the end, it now works better than expected.

There were several lessens learned along the way, many are simple and probable known by heavy software types, but for me they were large stumbling blocks.

The lessons learned:
  • When writing software it is very important to have a friend to review your code. The process of expainning code bring new eyes on the problem.
  • Interrupt Service Routines (ISR) should be as short as possible, I instinctive knew this, but initially did not follow my own advice. It is just too easy to add one more line to the ISR. Note: only the second (PinB) needs to be read here as the other (PinA) is already known to be HIGH, as the RISING edge of the pulse is what created the Interrupt.

void doEncoder0() {    // Rotary Encoder
    digitalRead(encoder0PinB) ? g_encoder0Pos++ : g_encoder0Pos--;
    return;
}

  • The variable used by the ISR should be declared as global and type "volatile byte", as:

// Set Initial Encoder Values
volatile byte g_encoder0Pos = 0;

  • Jeff suggested the "g_" conventions for global variables.
  • The main program routine that takes advantage of the data from the ISR should read it with one machine instruction, so that the process can NOT be interrupted by yet another ISR event. For an 8 bit processor that means use an assign statement between two variables of type byte. In my case, the flag that indicates that the assignment was complete (ISR data extracted), was another byte assignment of value zero to the source variable. Once the data is assigned, it can be accumulated or used as necessary.

int doGetEncoderValue() {
    byte tmp;

   // Get Encoder input
   tmp = g_encoder0Pos;
   g_encoder0Pos = 0;

   . . . . 

}

  • Each of these two assignments are NOT interrupt able and therefore does not pose a problem if another ISR event occurs. Yes, there is a very-very narrow window where one event may be lost, but for my Rotary Encoder application that will not be a problem. If I had used; "int", "long", or  "float" data type multiple machine instructions would have been necessary to complete an assignment. And then, if an event occurred during the the assignment, there would have been a good chance the data would have be corrupt.

The methods used within the test program, have already been incorporated into another more complex multi-tasking program that I am working on.

The following is an excerpt from that program:

        byte btmp; int itmp;

        lcd.setCursor(0,0);
        lcd.print("Adj Backlight");
        // Get and Decode Rotary Encoder Data
        btmp = g_encoder0Pos;
        g_encoder0Pos = 0;
                
        if(btmp < 128) itmp = btmp;
        if(btmp > 127) itmp = (btmp - 256);
          
        level += itmp * 16;
        
        if(level < 0) level = 0; // Constrain
        if(level > 256)level = 256;

        lcd.setCursor(0,1);
        if(level<10) lcd.print("0");
        if(level<100) lcd.print("0");
        lcd.print(int(level));
        
        // Some Sound Feedback, just for fun
        if(itmp) {
            tone(speaker, 2000 + 2 * level, 10);
            analogWrite(lcd_BL_pin,min(max(level,4),255));
            g_HoldOffReset = true;
            state=1;
        }

It will be just more fun stuff.


--

Thursday, October 6, 2011

Decoding a Rotary Encoder - Cont'd

See previous post.

This Rotary Encoder Test Program is archived here, and available for review. Actually, I am using a Teensy 2.0 for this effort.

Skip this post, if you are not into Arduino Programming.

It works GREAT!

UPDATE: The previous shown program was replaced with the following, smaller, faster Interrupts Handlers:


/*
 Coded for Teensy 2.0, but with maybe some different pin
 assignments should work with all Arduinos

 This is my LCD and Rotary Encoder Test and Development Sketch Template
 By: Eldon R. Brown eldonb@ebcon.com
 Oct 7, 2011
 
 The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 0
 * LCD D5 pin to digital pin 1
 * LCD D6 pin to digital pin 2
 * LCD D7 pin to digital pin 3
 * LCD R/W pin to ground
 * LCD 15 pin BackLight, to 220 ohm, to digital pin 9
 *
 * Encoder pins as defined in below
 */

// include the library code:
#include <LiquidCrystal.h>

// Setup Pins for Encoders, and .0022uf Cap to ground
#define encoder0PinA  5    // PD0
#define encoder0PinB 15    // PB6
#define encoder0Switch 7   // PD2
//#define encoder1PinA  6    // PD1
//#define encoder1PinB 16    // PF7
//#define encoder1Switch 8   // PD3

#define lcd_BL_pin 9    // PC6 -  The BackLight

#define INT0 0
#define INT1 1
#define INT2 2
#define INT3 3


// Set Initial Encoder
volatile byte g_encoder0Pos = 0;
volatile byte g_encoder0SwStat = 0;
//volatile int encoder1Pos = 0;
//volatile int encoder1SwStat = 0;

// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 3, 2, 1, 0);


//////////////////////////////////////////////////////////////
// Interrupt Handler /////////////////////////////////////////
//////////////////////////////////////////////////////////////

void doEncoder0() {    // Rotary Encoder
    digitalRead(encoder0PinB) ? g_encoder0Pos++ : g_encoder0Pos--;
    return;
}

void doEncoder0Switch() {     // Button
    g_encoder0SwStat = digitalRead(encoder0Switch);  
    return;
}

//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// Main Setup ////////////////////////////////////////////////
void setup() {

    // set up the LCD's number of columns and rows: 
    lcd.begin(16, 2);

    // Setup for Interrupts

    // Configure for Input
    pinMode(encoder0PinA, INPUT);    
    pinMode(encoder0PinB, INPUT);
    pinMode(encoder0Switch, INPUT);

    // Turn on pullup resistors, Pin must be in INPUT mode
    digitalWrite(encoder0PinA, HIGH);   
    digitalWrite(encoder0PinB, HIGH);
    digitalWrite(encoder0Switch, HIGH);

    // Set up for Interrupt
    // Only RISING is needed for Encoder    
    attachInterrupt(INT0, doEncoder0, RISING);
    attachInterrupt(INT2, doEncoder0Switch, CHANGE);
    interrupts();

    // Init LCD
    analogWrite(lcd_BL_pin, 128);
    // set up the LCD's number of columns and rows: 
    lcd.begin(16, 2);
    // Init Message
    lcd.print("--Initializing--");
    lcd.setCursor(0,1);
    lcd.print("   ebcon.com");
    delay(2000);
    lcd.clear();
    g_encoder0Pos = 0;

}

// Main Program Loop //////////////////////////////////////////
void loop() {
   
    doGetEncoderValue();
    //delay(100);
    //doBusyBox();
   
}

//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////
void doBusyBox() { // A Debug Function to make busy the processor
    delay(random(10,100));
    return;
} 

//////////////////////////////////////////////////////////////
int doGetEncoderValue() {
    volatile static int pos = 0;
    byte tmp;

    // Get Encoder input
    //noInterrupts();
    tmp = g_encoder0Pos;
    g_encoder0Pos = 0;
    //interrupts();
    
    if (tmp<128) pos += tmp;
    if (tmp>127) pos += tmp - 256;

    lcd.setCursor(0,0);
    // Print a message to the LCD.
    lcd.print("Pos= ");
    lcd.print(pos);
    lcd.print(" ");
    lcd.print(char(pos+65));
    lcd.print("   ");

    // Blink Cursor, for fun
    doBlinkCursor(15,1,!g_encoder0SwStat);
    return true;
}

////////////////////////////////////////////////////////////// 
void doBlinkCursor(char x,char y, char style) {
    switch (style) {
    case 1:        // Block Cursor
        lcd.setCursor(x,y);
        lcd.blink();
        delay(300);
        lcd.noBlink();
        break;
    default:        // Underline Cursor
        lcd.setCursor(x,y);
        lcd.cursor();
        delay(300);
        lcd.noCursor();
    }   
}

// End ////////////////////////////////////////////////////////


--

Monday, October 3, 2011

Decoding a Rotary Encoders - Cont'd

See previous posts.

Here is my Arduino Encoder Code for my archive, and others to review.

The input circuit is a pull up resistors and a cap to ground on each leg of the Encoder pins, the center Encoder pin is grounded. One pin is configured for interrupt while the other is configured for just input.

One interesting observation, there are two interrupts for each detent of the Encoder, rotating the knob very slowly will show an interrupt half way between the detents. The Encoder doc's do not imply this should be expected. Maybe I have the wrong doc's??

This interrupt handler works, it is my adaption of the published (original) code which is shown further below. I just futzed with the code to remove problems that I observed. I do not understand all that I know, maybe I just need more futzing.


///////////////////////////
// Interrupt Handlers
///////////////////////////
void doEncoder0() {          // This works !!! but not sure why??!!!
    static volatile byte _previous = 0;
    volatile byte _this = 0;

    volatile int junk = 2000, junk2; 
    while (junk--) junk2++;    // Delay for Debounce

    _this = digitalRead(encoder0PinA);

    if (_this != _previous) {
        _previous = _this;  
        if (_this == digitalRead(encoder0PinB)) {  
            encoder0Pos++;
        } 
        else {
            encoder0Pos--;
        }
    }
    return;
}


The following suggested Handler does NOT work for my simple Encoders.

void doEncoderX() {  // This should work but does NOT !! but not sure why??!!!
   
    if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
        encoder0Pos++;
    } 
    else {
        encoder0Pos--;
    }
    return;
}


The Setup is just three lines:

    pinMode(encoder0PinA, INPUT);    
    pinMode(encoder0PinB, INPUT);

    attachInterrupt(INT0, doEncoder0, CHANGE);




The Encoder Interrupts accumulate in "encoder0Pos", The shift (>>1) divides the value by two,  which is necessary as I want to count "detents" and there are two interrupts per detent. Setting "encoder0Pos" to zero, indicates all Encoder Interrupts have been accepted. Note: there is a very narrow window between these statements where a Interrupt could be lost, which is not big deal for my app.


 // Get Encoder input
 if (abs(encoder0Pos) > 5) chr += encoder0Pos; // For Accelerated Action
 chr += encoder0Pos>>1;
 encoder0Pos = 0;



Perhaps I need more desecrate component debounce, i.e., more capacitance on the input port.


--

Sunday, October 2, 2011

Decoding a Rotary Encoders

Decoding a Rotary Encoder is more difficult to use than I had thought. My test environment for the encoders is as described in the previous post.

A google search found several articles describing the problem, suggested solutions all seem to be less than optimum.

More coding, breadboarding, and research is necessary.

One problem may be that I am using less then optimum quality encoders, they were purchase on ebay for about $1.60 each. A quick search of Mouser Catalog lists many similar parts at the same price. Each have the same 20 (or so) pulses per revolution. Expensive (>$50) optical encoders typically have many more pulses per revolutions (>128) and therefore should provide more resolution. I don't think my projects require that much resolution (or expense).

I am going to check my car radio's volume and channel controls,  they seem to feel right and would be usable for most of my projects.

Of course, this is all necessary if the encoders are to be used in my future QRP projects. I am sure there is a workable solution, I just have not found it, yet!


UPDATE
My car radio Volume control appears to be an analog pot, with 32 indents over its range (about 300 degs). The Channel control appears to be an continuous rotating encoder with 16 detents per revelation, which is less than the 20 detents per revolution of encoders that I purchased.

-

Saturday, October 1, 2011

LC Display and Encoders Received

I received my ordered LC Displays and Encoder/Switches (see previous post).

Simple Development and
Test Configuration
It has been several years since I have programmed a PIC or other Micro Processor. The following is a quick build to provide a test circuit for getting back up to speed. The processor is the green circuit board on right side of photo. It is a Teensy 2.0 , which is a Arduino look/works-a-like.

The connection to the PC for programming and interaction is via the mini-USB. Power is supplied via the USB or external battery as shown here.

Add on software allows the Arduino Interactive Development Environmental (IDE) to work with the Teensy. In fact most Arduino Sketches (a C like program) run without alterations. I chose the Teensy because of it small size,  it is similar in size to my normal projects.

The Sketch that I have put together is to test and exercise of these parts. It is a simple multi-tasking Scheduler and State Machines. My goals is to develop and provide a simple template for my future multi-tasking Sketches. I plans to merge the Arduino or Teensy with my micro 9-Volt Transmitters (as previous posted) to create interesting more complex projects.

The two Rotary Encoders (center photo) are not completely hooked up yet. My plan is to use Interrupts to decode their input.

As seen by the photo, several tasks (4) provide sample text within several fields on the two line display and controls the LC BackLight Brightness. So far, the multi-tasking Scheduler and State Machines are working as planned.

I wrote several macros to implement Task Switching, Checkpointing, and Scheduling. I remember doing something similar in Assemble Code many years ago by counting clock cycles. These implementation in C was easy in comparison.

No, it is not a full featured multi-tasking Scheduler implementation, but it will do the multiple tasks/things that I require.


UPDATE
There appears to be an old and raging debate about the use and license of the Teensy and it's bootloader, see:

I do not know the current status of the concerns?

More research is necessary.

--

Friday, September 16, 2011

Project Parts

I found a couple of inexpensive parts on eBay, which will be used for a planed and future projects.

Links and photos are bookmarked here for later reference.

16 X 2  LCD 

2-Bit Gray Code Rotary Encoders
with Push Button

I hope the sellers do not mind as the Photos were copied here from their eBay web page.


UPDATE
I found a interesting Post on Arduino and Encoders, saved here for later use:

--

Thursday, September 16, 2010

In PIC Heaven

OK, I am now in PIC Heaven.

Long ago, I have used the Microchip 12C509 for many projects, but it is time to update.

In an attempt to find a PIC for some future projects, I ordered and received a few of the most popular.
  • Texas Instruments - MSP430 Launch Pad, Development and Evaluation Board = $4.30 with shipping at Mouser (how can they afford that!!!)
  • PJRC - Teensy USB Development Board - $18.00

Each Kit has a lot to offer; these are my initial reactions:
  • Microchip - has a lot of supporting chips and I think they have be around longer. Multiple programs to install and/or download. This should be easy, but I am have a hard time getting anything to work.  The Docs and Examples refers to different PIC than received?
  • ATmel Arduino - is VERY easy to program and it is quick to have something useful running. Just download one ZIP file and execute the main program.  The program contains links to read-only example files and a link to your project work space - very nice!
  • Solarbotics Ardweeny - is very small and the same ease of use as the Arduino and can be reduced to just the chip. A 6-pin programmer is needed, that is - a special USB to Serial Adapter (now on order).
  • Texas Instrument  MSP430 - Very inexpensive (evaluation board most function per $) - a little more difficult to program, but the chip has many built-in features, like on chip temperature. Two software packages are necessary to download and install; C and the Assembler. Demo code is a little difficult to find and set up - I will have to learn more.
  • PJRC Teensy - USB Development Board - It has onboard USB for programming and data transfer (I have this board on order)
Each of the above can be reduced to just an inexpensive PIC, for inclusion into a final project. Most PIC's are less than $2.00 - $3.00, availability, support (i.e., demo code), and easy-of-use (i.e., programming) will be the deciding factors.

I will update this post as I learn more.

.