Monday, March 19, 2012


 ARDUINO IN SYSTEM PROGARMMING AND STAND ALONE CIRCUITS


We use an Arduino to program other ATmega without bootloader . This technique allows you to use all flash memory for code and make boards using new ATmega, cheaper than those with bootloader.
The qualities that have made the success of Arduino are undoubtedly the open-source software, many libraries, a good hardware and a virtually infinite Reference that explains each possible use of the platform.
But if we use Arduino for a specific use, we can integrate it into a specific circuit and program the micro in a way that performs a single firmware. We may so remove the bootloader and leave to the firmware the entire program memory.
The ATmega328 has 32 Kbytes of flash, that when the chip is mounted on Arduino are not all available, as a portion is reserved to the bootloader, the purpose of which is to communicate with the IDE Arduino to load programs (sketch) to be performed. The same bootloader, on each power on or reset of Arduino, verifies the presence of a sketch in flash memory and executes it. The bootloader occupies a space of 512 bytes, in the case of Arduino UNO.
Well, in a stand-alone application the bootloader no longer needed.
The configuration of the micro ATmega328P needs, in addition to the power (+5 VDC to pins 7 and 20, GND to pins 8 and 22), a 16-MHz crystal between pins 9 and 10, two 22 pF ceramic capacitors from between these pins and GND, a 10 k Ω resistor between pin 1 and +5 VDC for pull-up the reset line.

Programming ATMEGA in stand-alone
Anyone knows that it is necessary program Arduino uploading a sketch via USB, using the software called IDE and the operation is quite simple.
We can see a screenshot of the IDE with an Arduino sketch loaded and UNO during the receipt of the sketch (notice the yellow LED on).
The technique will test allows the use of a board Arduino as ISP Programmer.
We start with the list of required materials:
•               Arduino UNO / Duemilanove (will be used as a programmer);
•               ATmega328P chip (chip to be programmed);
•               Breadboard and jumper;
•               a crystal of 16 MHz, two ceramic capacitors from 22 pF, a resistance of 10 K Ω 1/4 W, a resistance of 560 Ω 1/4 W LED 3 or 5 mm;
•               seven male-male jumper wires.
A resistance of 120 Ω 1/4 of watts, and an electrolytic capacitor or tantalum from 10 uF 10 ÷ 16 volts.
Now we prepare our target circuit and first of all insert the chip on the Breadboard, these are the connections to make:
•               through the jumper to be Breadboard connect pins 7 and 20 of the chip to the positive supply line (+5 volts);
•               in the same way we connect the pins 8 and 22 of the chip to the ground line supply (GND);
•               connect pin 1 of the chip to the +5 V line through the resistor of 10 k Ω;
•               insert the crystal to the pins 9 and 10 of the chip;
•               insert the two 22 pF ceramic capacitors; both must have a leg connected to GND, while the other will serve to connect a capacitor to pin 9 and the other to pin 10 of the chip;
•               insert one end of resistor 560 Ω at the pin 19 and the other end into an empty spot on the breadboard, and to this end we connect the anode LED(the longer pin) , whose other end (cathode) goes to GND;
 
At this point we can connect to the Arduino Breadboard using jumper cables under the following matches:
•               Arduino pin 10 goes to pin 1 of the chip;
•               Arduino pin 11 goes to pin 17 of the chip;
•               pin 12 of Arduino is connected to pin 18 of the chip;
•               pin 13 to Arduino pin 19 goes on the chip;
•               the +5 V pins of Arduino goes to the positive supply line of the breadboard;
•               any of the three GND pin of Arduino goes to the ground line of the breadboard.

Now look the software to reveal the “trick” that sends a sketch, using the IDE, to the chip on the Breadboard, bypassing Arduino that will play the role of Programmer ISP.
What we need to do is create a virtual board, starting from the original (corresponding to the model we are using Arduino) and making some simple but essential changes. We must first locate the file that is boards.txt containing all information relating to the various boards that the IDE shows us when we execute the command Tools->Board. Typically this file is located in the folder of the IDE software, the path X: \ mypath \ arduino-xxx \ hardware \ arduino, where X is the letter that indicates the logical drive and myPath the folder or location containing the program (xxx indicates the version of the program).
Now open the file with Notepad and see a long series of lines arranged in groups separated by a line consisting of a repetition of the symbol ”#”,each group representing a different board. The lines are identified by the initial code, the same for all, but different for the board, the name that will appear in the submenu Tools->Board is inserted in the first row in the group.
The code is represented by the word “uno” which is at the beginning of each line.
The line containing the word “name” (usually the first) is followed by “=” and then the name that the board will have in the IDE.
Other information that concern us are:
uno.upload.maximum_size = 32256: Sets the maximum capacity of flash memory that we can use in practice from 32 Kbytes of Flash which has the total ATmega328P we must subtract the space occupied by the bootloader, for the Arduino UNO is 512 byte;
uno.bootloader.low_fuses = 0xffuno.bootloader.high_fuses = 0xdeuno.bootloader.extended_fuses = 0×05; these three lines are the “fuse”, are used to set the behavior of the chip and are expressed with hexadecimal values;
uno.build.f_cpu = 16000000L: This line must correspond to the clock frequency for which the chip has been set, by means of the fused, expressed in Hz, 1 Hz 6,000,000 correspond to 16 MHz, precisely the frequency of the quartz or, more precisely, the present external oscillator to Arduino UNO; this value is used as a reference for timing controls of the software, such as delay () and millis ().

And now we create our own virtual board, writing these lines of code:

atmsa16.name=ATmega in Stand Alone (w/ Arduino as ISP)
atmsa16.upload.protocol=stk500
atmsa16.upload.maximum_size=32768
atmsa16.upload.speed=115200
atmsa16.upload.using=arduino:arduinoisp
atmsa16.bootloader.low_fuses=0xff
atmsa16.bootloader.high_fuses=0xdf
atmsa16.bootloader.extended_fuses=0x05
#### atmsa16.bootloader.extended_fuses=0x07
atmsa16.bootloader.path=optiboot
atmsa16.bootloader.file=optiboot_atmega328.hex
atmsa16.bootloader.unlock_bits=0x3F
atmsa16.bootloader.lock_bits=0x0F
atmsa16.build.mcu=atmega328p
atmsa16.build.f_cpu=16000000L
atmsa16.build.core=arduino

Following the approach of the file will separate this group of lines to those of other boards, inserting a line of ”#”.The end result should be:
We note that are varied: the code (atmsa16 instead of uno), the maximum_size (brought to its maximum capabilities of Flash, since we do not reserve space for the bootloader), then there a new line (atmsa16.upload.using = arduino: arduinoisp) that allows us to understand the IDE that will program the chip in stand-alone and not on the Arduino. Another new line is preceded by some “# # # #” that disables it, the reason is easily explained: the extended_fuses is set to 0×05, and in some special cases, during the transfer of the sketch could be an error bound the setting of this value.As we shall see later, simply change the following two lines of code:
 <em># # # # Atmsa16.bootloader.extended_fuses = 0x05</em>
<em>atmsa16.bootloader.extended_fuses = 0x0</em>7
thus activating the value 0×07 instead of 0×05, it will work out. Of course, this change should not be made before, but only if you get the error.

Program the micro
At this point we are ready for the final step: send our sketches to the chip mounted on the breadboard and then will test the operation separating it from Arduino.
To read the new board in the file, the IDE must be restarted, so if this program was open, when editing the file boards.txt must close it and restart it. To verify that our modification is successful, it is sufficient now run the command Tools->Board and check if there is now our “stand-alone” board, otherwise we should close the IDE and check the file boards.txt, because certainly we made ​​a mistake.
The technique used to send the sketch to the chip in stand-alone mode is very simple: First select the Arduino board that we are using as a programmer (eg Arduino Duemilanove or UNO) , just as we do for normal use of Arduino. Then select the Arduino serial port (the COM for Windows users) and recall from the IDE the sketch ArduinoISP, execute this command by clicking the Upload button on the IDE. After several seconds of the three flashing LEDs and Arduino to the breadboard of course (at the moment is physically connected to pin 13 of Arduino that, as we know, check out one of the three LEDs on the board) on the IDE will come the message “done uploading “.
Arduino is ready to play the role of Programmer ISP, select, now, our board IDE “ATmega Stand Alone (w / Arduino as ISP)“, without changing the COM.
We load the sketch “blink” and execute it again by clicking the Upload button on the IDE: LEDs and Arduino breadboard flash again, this time for a much shorter period, after which the IDE will show the message again “Done uploading”.
So our ATmega328P chip was programmed without having to physically fit on Arduino and now lives its own life. It is then ready to be mounted in the circuit which it is intended.
Of course, the chip can be reprogrammed at will with any kind of sketch.

Troubleshooting
At this point we have to solve three types of problem that may occur when we send the sketch to the chip stand-alone. The problems of’extended_fuses and of autoreset may occur on either Arduino Duemilanove or Arduino UNO, without that you can establish a certain rule.We must also emphasize that the remedies that will illustrate to 100% solve the problems, but must be applied only if the problem occurs.
We start from the situation that may occur if we use a blank chip, the Atmel set the fuse to make the chip work at 1 MHz with the internal oscillator. If we send a sketch directly, happens that the chip in stand-alone ignores the external crystal and times will be staggered: for example, the LED blink with the sketch will last about 16 seconds instead of 1 second. Simply, we set the fuse, the operation can be done easily by loading the bootloader on the chip before sending the sketch.
Before explaining this simple maneuver quickly clarify two points: the bootloader is sent once a chip virgin and will only serve to set the fuse, then it will become useless and the sketch overwrite it, if we had to first load the sketch, noticing the error, and then load the bootloader, no problem: the chip is set and we just have to resubmit the sketch. The simple steps that are going to describe will return very useful for cases where we wanted to prepare a blank chip to work directly on Arduino; is a good idea to have in the house a spare chip with bootloader of our board, so if you were unfortunately damaged the original, a simple substitution solves this problem immediately.
Here are the steps to follow:
•               prepare and connect the Breadboard Arduino as discussed previously;
•               We open the IDE and select the model we are using Arduino and port to which it is connected;
•               upload the sketch ArduinoISP to Arduino;
•               now execute the command Tools->Burn Bootloader w / Arduino as ISP;
•               After about a minute we loaded into the stand-alone chip the bootloader of Arduino boards (you may have noticed that in the IDE we’ve set our Arduino board).

As mentioned, the chip can be quickly mounted to receive the Arduino sketch, or leave it on the breadboard and repeat/execute the operation of sending the sketch stand-alone, this time the Blink will work perfectly.
Of course, other errors may occur, do not worry, keep reading this section and of course everything will be resolved.
So let the problem of ’extended_fuses: the rows of our virtual board we expected a double value for this cast, because it can happen (even though it is quite rare) that some boards do not succeed in this program merged with the value 0×05. During the upload of the sketch on the chip with stand-alone mode, the IDE will display an error message (written in red on a black background) that will indicate the need to use the value 0×07, if it appears that in practice warning means that we must close the IDE, open the file boards.txt and activate the relevant line, simultaneously disabling the other (with 0×05), as explained above. At this point we can repeat the test. We clarify that if the error occurs on a given board will always occur on this board, so the variation of the files should be done only once and permanently.
And now we see the problem, more frequent, about autoreset. When the serial chip (FT232RL on Duemilanove or ATmega8U2 of UNO) receives a signal from the USB port, sends the reset pulse to ATmega328, who then prepares itself to receive Data. This operation corresponds to the one you make every time you press the button “RESET” on the Arduino.
If the data do not arrive or if the reset was made manually, the sketches in flash memory chip ATmega328 is executed. When Arduino is used as ISP Programmer can happen that, if the autoreset is sent too early, the upload operation fails. In this case the IDE returns the following error: ”avrdude:stk500_getsync (): not in sync: resp = 0×15“.
The problem is solved by blocking the Autoreset. The 120 ohm resistance must be connected between the RESET pin of Arduino and +5 V, while the 10µF capacitor is connected with the positive pole to the RESET of Arduino and negative to GND.
With a jumper cable connect on Breadboard the RESET signal of Arduino.
The methods described should be used only if absolutely necessary.
Important note: the need to connect these components only when needed, is dictated by the fact that to load a sketch on the Arduino should autoreset, otherwise the upload will fail and we will get the error avrdude: stk500_getsync (): not in sync: resp = 0×00 – avrdude: stk500_disable (): protocol error, expect = 0×14, resp = 0×51, so if you see this error, know that you just have to “liberate” the pin “RESET” Arduino from the link with the Anti- autoreset.

When you walk into Etsy’s Brooklyn headquarters, it doesn’t take a rocket scientist to figure out that this is a website that sells hand-made goods. A receptionist sits behind a long rough-hewn wooden desk. Behind him are a floor lamp make from a tree branch and wallpaper that looks like stamped tin. Look up towards the fluorescent lights and Exit sign hanging from the 12-foot ceiling and there’s a length of air conditioning duct that has been yarn-bombed in gold and white by Austin, Texas-based Magda Sayeg, the mother of yarn bombing. Her knit graffiti collective, Knitta Please, is credited with stitching together the whole yarn bombing thang.
“When people come to visit we wanted them to feel like they were coming to Etsy, so to the extent that it’s possible, everything here comes from the site or was hand-made,” explains Adam Brown, Etsy’s press guy. Mission accomplished.
En route to the city-room size workspace, there’s another indication that you’re not in a typical corporate office: an indoor bike rack. The day in late January I dropped by there were only a dozen bikes parked at the rack but it was pouring outside. A white wall behind the bike rack was turned into a mural with black line drawings made during a party for Etsy’s fifth anniversary. The website asked for customers to tweet about their favorite purchase and among the fondest purchases were a Mason jar pin cushion, subway token cuff links, and emoticon mittens.


As someone who admires the work of talented woodworkers, right away, I keyed in on the hand-made desks in the big room. Although most were done so that the natural grain showed, one had been painted orange with purple stripes and another had blue waves painted along one edge with a hand sticking out and a cartoon bubble with the word “help.” I presume this was an Etsy employee who was feeling a bit overwhelmed by the workflow. A couple of the desks had improvised extensions so they could be used as standing desks. The desk is the work of Brooklyn woodworkers Craig Montoro and Bryan Mesenbourg who have a business called Parts and Labor Workshop. The mod to raise it so it can be used while the worker is standing was done by Reade Bryan of Etsy’s office management team. It was done in such a way that if the employee decides they don’t want a standing desk after all, it can be used as a sit-down desk. (Pretty cool but not as cool as the standing desks in the San Francisco office of Instructables.com, where treadmills have been placed in front of some.)
I noticed that some of the Parts and Labor Workshop desks at Etsy had a small shelf created in a space that looked like it had been made for a drawer. Other desks have a few drawers made of different types of salvaged wood stained a variety of hues. Etsy’s Director of Community, Vanessa Bertozzi, has one such desk. Bertozzi manages a team that does outreach and education to Etsy sellers, helping them develop their businesses. She is one of the 20 and 30-somethings at Etsy who actually remembers the Whole Earth Catalog, which has been been described as “Google before the Internet.” Bertozzi keeps a copy of the Whole Earth Catalog on her handmade desk as a reminder of Etsy’s — and the Net’s — roots.
I asked Adam Brown who had done the tapestries hanging on the wall around some conference rooms and he promptly explained that they were, in fact, painted murals, not fabric. They were done in 2010 by the Brooklyn-based painter Maya Hayuk, who was the subject of one of Etsy’s excellent video podcasts. My wife Pamela, who is also a painter, noticed that some of the murals included shadows painted around the images of the fabric, which made them look like there were indeed tapestries hanging on the wall.
A lot of the stuff sold on Etsy is in some way playful and the Brooklyn headquarters clearly reflects that spirit. Rather than name the conference rooms by number, Etsy decided to name them after a band and a type of food, so there are conference rooms named Pjork, Oreo Speedwagon, and Soy Division. A lounge has been named Wu Tang Clams and it has a large mural created by Etsy video producer Eric Beug with the help of some co-workers and friends. Because the cavernous main work room can get a bit noisy (many of the Etsy employees were wearing headphones), there are some small rooms for private phone conversations. One has an old-fashioned radio and art deco TV screen, another comes equipped with larger than life plush versions of a cuckoo clock and a manual typewriter.
Paint-by-numbers mural in the Etsy lounge (Deer in Sunlight)
Not only can Etsy employees bring their bikes to work, they can also bring their dogs. Adam Brown estimated that there were sometimes as many as 15 Canine-Americans on the premises.
“It’s nice for people like me who don’t own a dog but like to have dogs around,” he told me. “Then I can just pet them and play with them and never have to clean up the poop or pay for a vet.”

The octopus tentacle breaking through faux brick wall was made by Redding, CT-based sculptor/painter David Cramer whose ArtAkimbo shop on Etsy features “Functional art, Eyeglass stands, Tentacles, Merriment.” Some of the eyeglass stands consist of a nose and mustache. The reindeer head with yarnbombed antlers is the work of Lana “Plushinator” Crooks of Chicago who has been referred to as the “hardest workin’ lady in sew business.” Her shop is plushinator.etsy.com.

Wednesday, March 14, 2012


My alt.GDC series came to a close on Friday, but I still have one story I’ve been wanting to tell. In my day job, I work as a game designer for a company called Toys for Bob which recently released the wildly popular game called Skylanders: Spyro’s Adventure. The game comes with an external device (called the Portal of Power) that communicates with your console and action figures that can be identified by the portal and brought to life in the game. You swap out characters as you play by changing the character on the portal. Players can also expand their selection of playable characters by collecting more toys.
Before I went into GDC on Friday, I swung by the Toys for Bob offices in Novato, CA and sat down with Robert Leyland, the technical engineer behind the Skylanders hardware, and I-Wei Huang, the character and toy director (also known to MAKE readers as magazine and site-contributor CrabFu), to discuss the process of developing this innovative title.
MAKE: What can you tell us about the early development you did on the Skylanders concept; where did you start?
Robert: We started with a bunch of prototype ideas… When the Wii came out, it had these new controllers and people started thinking: We could make more devices, more accessories, and you saw this with things like Guitar Hero, Wii Fit, the Tony Hawk skateboard. So we wanted something that would connect to the Wii to create a physical device.
There was a period there where we said “But how are we going to connect it? Will we need to mount a Wii-mote in it?” And right around that time, on MAKE or Instructables, I can’t remember where – we saw it on Gizmodo, somebody published a hack about how to use a Wii Nunchuck to control an R/C helicopter and we thought: Whoa, that’s really pretty cool. And we looked and sure enough they weren’t just wiring to the potentiometers in the controller, they were using the output signals and there was a bunch of software published that showed that you could get the signal data from the Nunchuck controller. And I thought that was neat that they’d done that, but I also thought, if I can pretend to be a Wii Nunchuck controller I can talk to the Wii and we can go the other way.
Robert Leyland at his desk. I think he likes his job.

So a few weeks later, we have an Arduino and a circuit board and some wires, and on the Arduino I’m pushing a button and its going through the controller and being registered in our script as a button press from the Wii. So if we’re controller 2, we can talk to the Wii while the player’s controller 1. We did a few tests and proved that it all worked. But then we talked to Nintendo and found out that there’s only about 15mA of power available to the controller which would barely run an LED, let alone a CPU or anything else, and there were way too many restrictions so we thought we’ve got to find some other way. Eventually, we ended up going through the USB port. And then somewhere along the line, somebody came up with the idea of “making toys come to life” and we thought: That’s good, that’s fantastic, in hindsight the best idea we’ve ever had. And we looked at different ways of connecting the toys. We looked at little contacts on the toys, different RFID techniques, and we finally settled on one of those, partly because it was an ISO standard, and partly because there were open source libraries published to access the RFID controller.
So, we got an RFID controller from Turkey, the Arduino from Italy, and the USB connection which was wired here in California with a software library from some guys in Germany – you can just pull all of these pieces together and gosh, you can quickly prototype something which is really neat.
The first connection we had was only 5 bits; we were pretending to be a keyboard and whenever you got a keystroke it said “Oh, that’s key X, so that’s Spyro” or “Key 7, that’s Bash.” So with those individual keystrokes you could essentially see a character, but we knew we needed more IDs than that, so we eventually wrote a protocol that would send longer data sequences. And it evolved from there.
The original portal prototype made from kitchen sink and toilet hardware.
MAKE: What kind of hardware did you use to build the original portal prototype?
I-Wei: We spent a lot of time going through hardware stores, office supply, and craft stores looking for things we could use. It’s fun, it’s really similar to what I do with my steam-powered robot stuff (CrabFu Steamworks), you go into a store with the mind of “I need something that has this shape and size.” It’s a different way of shopping, you’re pattern matching. “What could I find that would fit that look, if I painted this thing, or if I cut this part off, I don’t need this section, but if I take this other part and put it here…”
Robert: And it can be any part of the store; it could be the toy section, it could be the kitchen section, it could be the plumbing supply section… In the plumbing section we found a pipe that was the right diameter and flared at the bottom. It was for a toilet! But it enabled us to put a light in the bottom, a sheet of translucent plastic on top and a ring of LEDs around it to create the effect we wanted.
I-Wei: And on the bottom where the main LEDs are we used a kitchen sink drain because it had a nice reflective surface, it was already a bowl shape, so the light on the bottom would be like a flashlight, shining all the light upwards.
MAKE: And you were using Arduino for the electronics?
Robert: Yea, I think the early prototypes used a Boarduino from Adafruit. Actually even earlier than that I was using two 555 CMOS chips timed together to control the LEDs and they were wired to a “magic moment” button, so in our demos someone would put the toy on the portal, but I was off to the side pushing the button going “pay no attention to the man behind the curtain.”
MAKE: At what point in prototyping the portal technology did you show it off to Activision?
I-Wei: Pretty early on. This was the kind of thing that we had to see the idea internally to prove to ourselves that we weren’t crazy, but also if you just imagine Skylanders as a pitch on paper, I don’t think it would have been very successful. But as soon as we made the first hand-made sculpey figure and you put it in your hand, you start to get it, and then having a portal that actually worked, where as soon as you put a character on it you see a character on screen running around a simple world, that’s all you need to sell it and we had that really early on.
MAKE: I-Wei, what can you tell us about the making of these incredibly popular toys?
I-Wei: The quality of the toys that are on the shelves today is the result of our ignorance in the toy industry. We weren’t toy makers, so we spent a lot of time going through every little detail with these characters because we wanted a cool toy, not just a good-enough toy for our age group. If you look at other toys in our price range, the amount of paint, the amount of detail isn’t there. You’d say “Oh, that’s a cool toy for a kid,” but to an adult it wouldn’t be as interesting. We just didn’t have that filter of “This is good enough to sell.” We wanted you to be able to look at the toy by itself, apart from the game, and say “Wow, that’s a cool toy!”
Name those Skylanders! (Trick question)The humble beginnings of Skylanders
At the time we had no experience making toys and the kind of mold-making you need for mass-producing toys so we relied on an external company to make them. We would give them sketches of characters and in-game models, animations, screenshots, and everything, and they would produce a toy that we would then tweak and tune to get the likeness and personality to show through a little bit better and that process could take many many months. We did many iterations of the character and paint and pose and everything.

MAKE: How has this process been improved since the completion of the first game?
I-Wei: Now we have a 3D printer in our studio, so we can do everything internally. We take our in-game model and we res it up in Z-Brush so it looks great and has all kinds of detail in it. Then as soon as we have the high-res version we put it in different poses because it’s also an in-game model which already has a rig. We usually try about 3 poses and then we just export it, hit a button and the next day we have a 3D print (It’s actually a bit longer process to prep a 3D print in color). So this time around we have much more control over how the toy’s look. The 3D printer has sped up a process that could take, from final concept to a toy that looks great, around four months. Now we can have a model roughly done in about a week. We’ve greatly streamlined this process.
How many dollars does that guy owe me?Several 3D Prints of Terrafin striking a pose
MAKE: In closing, do you have any advice for getting publishers or investors to subscribe to a crazy idea like this?
Robert: When you pitch your prototypes, you want to make sure that they are good quality, they’re neat and tidy. Take the time to put it in a box and package it up so it’s not just written on the back of a fish and chips wrapper.
I-Wei: Especially for me, on the visual side that’s vastly important because you’re really selling your idea and you want to make sure that the first impression is good. Make sure everything is as polished as you can make it. It’s harder to sell a tech demo. If it’s a beautiful looking thing and you can grab them by the emotional strings you don’t have to explain the tech.
Robert: Another piece of advice when prototyping: Go with standards.
Don’t try to own the entire space. The more you can do something unique, find a niche that works with other standards, the better off you are, because people will find ways to use your stuff that you didn’t envisage. It seems obvious, but sometimes it’s not.



As an intern in the Lab, I have the chance to work with professional makers — a group dedicated to the magazine, the readers, and the whole maker movement. As a student in the first year of the MAKE high school class, I get to see the awesome power of this movement as it captivates my peers. As a class, we have planned and built a geodesic dome large enough to house a car, two T-shirt cannons for school sporting events, PVC go karts to be entered in pedal-powered races, and much more. This semester, we have the opportunity to work on a project of our own design. I want to use RFID technology to unlock my car door as I approach.
Because my car has manual locks (it’s a 98 Toyota Tacoma), I must use an Arduino to translate the RFID reader’s signal into mechanical motion. Most projects online only pertain to cars with an electric locking system already in place, so this part of the project is truly my own.  I am using this 12V solenoid, wired to my car battery, to provide the mechanical motion to push the lock.

To pick up the RFID signal, I’m using this Parallax RFID reader, which will be mounted into the wall of my car door, directly under the handle.


Finally, to translate the RFID signal into the solenoid’s motion, I am using an Arduino Uno board, powered from a battery pack.

The RFID reader will be wired into the Arduino’s pins, as will my 12V car battery and the solenoid. The Arduino acts as a gate: when the reader detects the correct RFID tag, the Arduino opens the connection between my car battery and the solenoid, and the door unlocks.  Voila!
Before I set the components up inside my door, I have some potential problems to deal with. I don’t want the to be harmed by the vibration in the door when I shut it, so I think I’ll be mounting everything in a project box with ample styrofoam protection. However, I want the battery pack to be accessible, because removing the door panel repeatedly to change them will be irritating. For this, I think I’ll drill a small hole in the door panel, and run the battery pack out to the small door pocket.
I’m in the process of removing my door panel, and I’ll tackle the Arduino code next-there are ample RFID libraries online, thanks to the vast programming community. Stay tuned for the next steps of my project as I near completion, and feel free to pose questions or provide possible solutions to my problems! Until next time,

GSM Remote Control – Temperature Control Part 2 – Schematic

The full GSM thermostat is managed by a Microchip PIC18F46K20-I/PT microcontroller, programmed with a firmware that controls the temperature and takes care of the communication with the GSM module which is the component named GSM; this is, in fact the small board hosting the cell, so the pins’ numbers refer to the used pin-strips’ contacts.
The firmware reads the room temperature by means of a smart probe Dallas DS1820, it controls the logical condition of the opto-isolated input and commands the relay when needed.
TDG139 Schematic
Temperature Control Schematic
Having said that, let’s now take a look at the electric scheme, starting by the power block, that from the input voltage (power applied to PWR, + and – must be a continuous current at a value between 5 and 32 V) gets a stabilized component  of 3.6 V width by means of a switching regulator. The input voltage is filtered at the bottom by the diode protecting against polarity inversion (D1) through condensers C1 and C2. Fuse F1 enables you to protect both the circuit and the power source in case of short circuit in the integrated regulator discussed below. The regulator is a U1 (a MC34063) and acts as a DC/DC converter step-down; it is used in the classic configuration of  the series PWM regulators charged by inductance, whose output voltage depends on the energy stored in L1. The voltage it provides is stabilized providing feedback to the DC/DC through the demotion of a portion of the leveled component by condensers C4 and C5, made by the resistive divider R2/R3.The 3.6 volts present in these condensers are widely filtered by other condensers placed on the power lines of the microcontroller and of the GSM module; which presents, during transmission, absorption peaks compensated for by C7, C8, C13, C14, C15 and C16, thus avoiding than an impulsive current request may cause the microcontroller to be disturbed.
The microcontroller is used in the configuration with an internal clock oscillator; both the scheme and the printed circuit are nevertheless equipped with external quartz, intended for future developments. Once the I/O lines have been initialized, the microcontroller verifies the logical state of the opto-isolated inputs at voltage level related to line RB4 as well as that of lines RC4, RC5, RD0, RD3, RX, which are needed to receive the main notifications from the cellular module; more specifically, RD3 is used to detect incoming calls (it interfaces with the RI of the cellular module), while RC4 controls the GSM “field LED”, by reading the corresponding output status. The PIC understands the conditions of the radio coverage from the frequency and duration of the impulses, and then adjusts accordingly.
The microcontroller contains a UART accessible via pins 44 (transmission) and 1 (reception) which it uses to communicate with the mobile; more precisely, through the first pin (TX), it cyclically questions the module to check whether any SMS has been received, whereas both TX and RX are used for the communication between the microcontroller and the GSM module when making calls and receiving or sending messages.
Regarding the UART, the following control signals are used: CTS (Clear To Send) RTS (Request To Send) and DCD (Data Carrier Detect), which correspond to those of the cellular module being used.  Lines RC5 and RD0 complete the set of I/Os destined to the mobile; the former controls the turning on and off of the GSM (through a transistor placed in the small board of the mobile), the latter takes care of resetting the mobile. The button for locally handling the operating mode of the device is read through line RA3, configured as input and equipped with an external pull-up resistor (R11), therefore active at a low level. Special attention deserves the management of the inputs since here, compared to the general scheme of the modular remote, we find a variation: to directly read the condition of the room thermostat contact of the system where the circuit is applied, it must bypass optocoupler U4, for which reason it is not used; let’s imagine to short-circuit pin 1 with pin 4 and pin 2 with pin 3. Input IN1 reading takes place by means of line RB4, set as an input and with an internal pull-up: when the contact is open, it remains at a high level, while when the thermostat closes its contact it assumes the logical zero. IN1 must be connected to the contact normally opened by the eventual thermostat already placed in the system, but only if the enslaved mode (T) is to be activated: in fact, in this mode, relay RL1 follows the performance of the thermostat. IN2 is read by means of RB5, which acquires the U5 optocoupler output transistor status; the input is active when under voltage between 3 and 30 V. When a 3-volt voltage (at a minimum) is applied to input IN2, the optocoupler’s LED is switched on and the output phototransistor is in conduction state; therefore, the collector (pin 5) is at about zero volt during the I/O initialization due to the fall on the resistor of the internal pull-up that was configured. If the input is not polarized, the opto-isolator gets inhibited and its pin 4 is at a high level. Input IN2 can be used to monitor the state of an electric line, for example the one belonging to the alarm indicator of the boiler. Note that IN1 only determines local actions and only in the mode enslaved to the existing thermostat, while IN2 starts the execution of the alarm sequence, which, according to the settings made by the user can be sending SMS or direct calls to the numbers stored in the list. The sequence starts when the input undergoes a potential difference over the threshold one (about 3 volts).
As far as the outputs is concerned, there is just one here, corresponding to RL1. When it has to enable the boiler or the conditioner, the microcontroller puts its own line RE2 at a high logical level, saturating transistor T1 and therefore commanding relay RL1 to be excited; every activation is indicated by LD1, fed along with the relay coil. To protect the collector junction of the transistors during the passage from saturation to interdiction, when the relay’s coil inductance generates inverse voltage peaks, we have connected a diode along with the coil that eliminates such impulses. The complete exchange is available from RL1 so as to manage circuits that require a contact that is normally closed or normally open.
The PIC setting takes place in-circuit, through connector ICSP, related to lines /MCLR, PGU and PGC; the ICSP also receives the power and the mass of the microcontroller.
As this was not enough, we have also prepared a serial communication interface useful to allow the setting of the operating data (for example, the list of phone numbers, the management of input levels, the text of the SMS sent by the circuit in reply to the commands, etc. through a PC: this allows to program a remote control before making it operative and save on the configuration SMS, that can anyway be used, but better if this is done when the system is already installed in its final position.  Having already used the UART to communicate with the cellular module, the serial communication takes place through lines RE0 and RA5, respectively used as TX and RX, the AN3, assigned to the A/D inner converter is used to sense the presence of the 5 volts, and therefore the insertion of the connector. The serial interface is at TTL level, and can be easily connected to a USB converter, as for example the FT232 by FTDI, to interface the microcontroller with a PC including a USB. For the interface you can use the small module FT782M made by Futura Elettronica (www.futurashop.it).
Always about the configuration of the unit, note that the corresponding data is not saved in the microcontroller’s EEPROM, but in an external memory chip, named 24FC256-SN; it is a 256 kbit EEPROM CMOS 256 with serial access and I²C-Bus interface. To communicate with it the microcontroller starts lines  I/O RD4 and RD5 respectively used as SDA (data line) and SCL (clock line). Moving the configuration data of the remote into an external memory has allowed us to take advantage of the internal EEPROM of the microcontroller to extend the available functions.
The room temperature is sensed by the microcontroller with the help of a vey precise probe, the DS1820 from Dallas Semiconductor, able to measure temperatures in the range 23 °F÷302 °F (-5÷150 °C), with an accuracy of only ± 32.9 °F (0,5 °C) (in the field 14 °F÷185 °F (-10÷85 °C), scan them and make the available on a serial line, connected to the RC0 pin of the microcontroller. The DS18B20 expresses the sensed temperature with an 11-bit resolution; to question it, the microcontroller uses the command “Convert T” (code 44h) corresponding to the launching of the measure conversion. The probe communicates using the one-wire protocol, which allows a two-way communication on a single wire; for that purpose the R19 pull-up resistance is requested. In this application we use separate lines for data and power, but the DS18B20 could also work putting them together, that is using the one-wire protocol to its full potential.

Our weather station LIVE


There are several softwares that enable the publication of the weather data of a professional weather station, but they all work on PC, so we should connect the weather station to a computer and leave it on, the idea is not good because the computer takes up space and consumes a lot. At a time when we should spare the energy, its not a good thing.
The project we’re talking about instead operates as a stand-alone application and allows you to publish the weather station data independently on http://www.wunderground.com, “forgetting” the PC consumption and even the desk space.
Arduino controls the dialogue with the weather station to acquire the data and also the Ethernet interface to transfer them, by making the necessary connection to the Internet via ADSL, passing by a router pointing to the IP address of the Weather Underground site and transferring information using the TCP / IP.

Our project
This circuit reads data from a weather station with serial interface and upload the data collected on http://www.wunderground.com.
Not all stations are equal, therefore, our circuit can not be universal but it is indicated specifically for stations La Crosse WS2355, WS2300 or WS2350.
The choice of weather station WS23xx was dictated primarily by a consideration: it has a convenient serial interface to connect and dialogue with a microcontroller such as Arduino.
We chose www.wunderground.com site because it allows anyone to upload their weather data, but also to monitor the temperature, humidity, pressure, wind etc. on line. Also on this site there are many widgets that allow you to integrate data in website or blog.
An example is the Widget for the home page of Google.
The data sent by users are publicly available, then from the home page we can specify the geographic area that interests us and we will see a screen that lists all of the corresponding stations.
How does it work?
The system has two circuit: one is the famous Arduino UNO and the other is a shield that integrates the Ethernet module WIZnet (you may, of course, use the the original Ethernet Shield), as well as a TTL/RS232 logic level converter MAX238 type. The converter allows you to adapt the serial levels of weather station to the TTL levels of Arduino.
Please be aware that the communication port of the weather station is not a simple RS232, because it has no ground reference. The DTR line must have a negative voltage while the RTS must be positive. The lack of common ground leads to the hypothesis (remember that there is no official document) that these two lines are taken as a reference of logic levels used in communication. It is a system that not only allows the use of serial connections relatively long, but also gives the opportunity to agree devices with different voltage levels on the serial port.
To communicate with La Crosse, the speed of the serial device (in our case, the Arduino module) must be set to 2,400 bps, with blocks of 8 bits, no parity and one stop bit (2400-8-N-1).
The memory map of the weather station, like many other unofficial information on the WS2355 is on the site http://www.lavrsen.dk/foswiki/bin/view/Open2300/WebHome.

The hardware
The jumpers on the lines T3IN and R3OUT (respectively RS232/TTL converter output and RS232/TTL converter input) let you choose which lines use for Arduino communication: we give you the opportunity to choose if use the serial hardware TXD and RXD or the two I/O digital D2 and D3 emulating a serial port with the appropriate library that can be downloaded from the website http://arduiniana.org/libraries/newsoftserial.

R1: 470 ohm
C1: 1 µF 100 VL
C2: 1 µF 100 VL
C3: 1 µF 100 VL
C4: 1 µF 100 VL
U1: WIZNET
U2: MAX238CNG
LD1: led 3 mm red

- socket 12+12
- Strip male 3 via (2 pz.)
- Jumper (2 pz.)
- Strip female/male 6 via (2 pz.)
- Strip female/male 8 via(2 pz.)
- Strip female 10 via (4 pz.)
- DB9 male
- PCB


 

The sketch
/*

****************************************************************
*  Name    : Personal Weather Station to wunderground.com      *
*  Author  : Landoni Boris                                     *
*  www.open-electronics.org                                    *
*  blog.elettronicain.it                                       *
*  www.futurashop.it                                           *
****************************************************************

http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol#Example_URL

action [action=updateraw] -- always supply this parameter to indicate you are making a weather observation upload
ID [ID as registered by wunderground.com]
PASSWORD [PASSWORD registered with this ID, case sensative]
dateutc - [YYYY-MM-DD HH:MM:SS (mysql format)] In Universal Coordinated Time (UTC) Not local time
winddir - [0-360 instantaneous wind direction]
windspeedmph - [mph instantaneous wind speed]
humidity - [% outdoor humidity 0-100%]
tempf - [F outdoor temperature]
rainin - [rain inches over the past hour)] -- the accumulated rainfall in the past 60 min
indoortempf - [F indoor temperature F]
indoorhumidity - [% indoor humidity 0-100]
softwaretype - [text] ie: WeatherLink, VWS, WeatherDisplay

windgustmph - [mph current wind gust, using software specific time period]
windgustdir - [0-360 using software specific time period]
windspdmph_avg2m  - [mph 2 minute average wind speed mph]
winddir_avg2m - [0-360 2 minute average wind direction]
windgustmph_10m - [mph past 10 minutes wind gust mph ]
dewptf- [F outdoor dewpoint F]
dailyrainin - [rain inches so far today in local time]
baromin - [barometric pressure inches]
weather - [text] -- metar style (+RA)
clouds - [text] -- SKC, FEW, SCT, BKN, OVC
soiltempf - [F soil temperature]
 * for sensors 2,3,4 use soiltemp2f, soiltemp3f, and soiltemp4f
soilmoisture - [%]
* for sensors 2,3,4 use soilmoisture2, soilmoisture3, and soilmoisture4
leafwetness  - [%]
+ for sensor 2 use leafwetness2
solarradiation - [W/m^2]
UV - [index]
visibility - [nm visibility]

http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?ID=KCASANFR5&PASSWORD=XXXXXX&dateutc=2000-01-01+10%3A32%3A35&winddir=230&windspeedmph=12&windgustmph=12&tempf=70&rainin=0&baromin=29.1&dewptf=68.2&humidity=90&weather=&clouds=&softwaretype=vws%20versionxx&action=updateraw

mappa ws2300

Command Hex Digit    Command Hex Digit
82  0     A2  8
86  1     A6  9
8A  2     AA  A
8E  3     AE  B
92  4     B2  C
96  5     B6  D
9A  6     BA  E
9E  7     BE  F

*/

#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h>
#include <NewSoftSerial.h>

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0,145 };
byte server[] = { 38,102,136,125 }; // http://weatherstation.wunderground.com/

#define UPDATE_INTERVAL            300000    // if the connection is good wait 60 seconds before updating again - should not be less than 5
unsigned long update=0;

NewSoftSerial mySerial(2, 3);   //NewSoftSerial mySerial(rx,tx);

const int ledPin = 6; // the pin that the LED is attached to
const int rts = 4;
const int dtr = 5;
String id = "xxxxxxx";
String PASSWORD = "xxxxxxx";
boolean upload=1;
boolean leggicontinuo=0;

Client client(server, 80);

void setup() {
  Ethernet.begin(mac, ip);

  digitalWrite(ledPin, LOW);
  // initialize serial communication:
  Serial.begin(2400);
  Serial.println("Goodmorning WS2300!");
  // set the data rate for the NewSoftSerial port
  mySerial.begin(2400);

  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  pinMode(rts, OUTPUT);
  pinMode(dtr, OUTPUT);

  digitalWrite(rts, HIGH);
  digitalWrite(dtr, LOW);
  delay(2000);
  digitalWrite(rts, LOW);
  digitalWrite(dtr, HIGH);

  for (int i=0;i<10;i++){
    digitalWrite(ledPin, HIGH);
    delay(200);
    digitalWrite(ledPin, LOW);
    delay(200);
  }

}

void loop() {

  int incomingByteSer;      // a variable to read incoming serial data into
  // see if there's incoming serial data:
  if (Serial.available() > 0) {
    // read the oldest byte in the serial buffer:
    incomingByteSer = Serial.read();
    // if it's a capital H (ASCII 72), turn on the LED:
    Serial.flush();
    if (incomingByteSer == 'o') {
      String data=getTime();
      Serial.print("ora ");
      Serial.println(data);
    }  

    if (incomingByteSer == 'd') {
      String data=getDay();
      Serial.print("giorno ");
      Serial.println(data);
    }
    if (incomingByteSer == 't') {
      String data=getTemp(1);
      Serial.print("temperatura interna F ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'T') {
      String data=getTemp(0);
      Serial.print("temperatura esterna F ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'h') {
      String data=getHum(1);
      Serial.print("umidità interna ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'H') {
      String data=getHum(0);
      Serial.print("umidità esterna ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'p') {
      String data=getPress(1);
      Serial.print("pressione hPa ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'P') {
      String data=getPress(0);
      Serial.print("pressione Hg ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'w') {
      String data=getWind(0);
      Serial.print("wind speed mph ");
      Serial.println(data);     

    } 

    if (incomingByteSer == 'W') {
      String data=getWind(1);
      Serial.print("wind dir ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'r') {
      String data=getRain(1);
      Serial.print("rain 1 ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'R') {
      String data=getRain(0);
      Serial.print("rain 24 ");
      Serial.println(data);
    }  

    if (incomingByteSer == 'e') {
      String data=getDew();
      Serial.print("dew point ");
      Serial.println(data);
    } 

    if (incomingByteSer == 'U') {
      readws();
    } 

    if (incomingByteSer == 'u') {
      pubblica();
    }

    if (incomingByteSer == 'a') {
      if (upload==1){
        upload=0;
        Serial.println("Disattivo l'upload automatico ");
      }
      else
      {
        upload=1;
        Serial.println("Attivo l'upload automatico ");
      }
    }

    if (incomingByteSer == 'A') {
      if (leggicontinuo==1){
        leggicontinuo=0;
        Serial.println("Disattivo lettura continua ");
      }
      else
      {
        leggicontinuo=1;
        Serial.println("Attivo lettura continua ");
      }
    }

    // if it's an L (ASCII 76) turn off the LED:
    if (incomingByteSer == 'L') {
      digitalWrite(ledPin, LOW);
    }
  }

  if (upload==1){
    if (millis() < update) update = millis();
      if ((millis()% 1000) < 2){
        delay (100);
        Serial.print(".");
      }
        if ((millis() - update) > UPDATE_INTERVAL){
            update = millis();
            readws();
            pubblica();
            Serial.println("tempo impiegato per fare la pubblicazione: ");
            Serial.println(millis()-update);
        }
  }

  if (leggicontinuo==1){
    if (millis() < update) update = millis();
      if ((millis()% 1000) < 2){
        delay (100);
        Serial.print(".");
      }
        if ((millis() - update) > UPDATE_INTERVAL){
            update = millis();
            readws();
        }
  }

}

void pubblica()
{

  int timeout=0;
  int skip=0;
  String inString="";
  digitalWrite(ledPin, HIGH);
  Serial.print("connecting  ");

  if (client.connect()) {

    Serial.println("connected");
    //client.println("GET / HTTP/1.0");
    Serial.print("GET /weatherstation/updateweatherstation.php?");//modificare qua.
    client.print("GET /weatherstation/updateweatherstation.php?");//modificare qua.
    pubbws();
    client.println(" HTTP/1.0");
    Serial.println(" HTTP/1.0");

    Serial.print("HOST: ");
    client.print("HOST: ");
    client.println("http://www.wunderground.com");
    Serial.println("http://www.wunderground.com");
    client.println();
  } else {
    Serial.println("connection failed");
  }
  while (!client.available() && timeout<50)
  {
    timeout++;
    Serial.print("Time out ");
    Serial.println(timeout);
    delay(100);
  }

  while (client.available())
  {
        char c = client.read();
          if ((inString.length())<150){ inString.concat(c);}
  }         

  client.flush();

      if ((inString.length())>5)
      {
              Serial.print("Risposta ");
              Serial.print(inString);
      }              

   if (!client.connected())
   {
        Serial.println("disconnecting.");
        client.stop();
        delay (1000);
   }
   digitalWrite(ledPin, LOW);

}

void readws(){

      Serial.println("URL ");
      Serial.print("http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?");
      String temp =getDay();
      String temp1=getTime();
      if ((temp.length()>6) && (temp1.length()>4)){
        Serial.print("ID=");
        Serial.print(id);
        Serial.print("&PASSWORD=");
        Serial.print(PASSWORD);
        Serial.print("&dateutc=");
        Serial.print(temp);
        Serial.print("+");
        Serial.print(temp1);
        scrivimem(temp,0);
        scrivimem(temp1,20);
      }
      else
      {
        Serial.println("Lettura data/ora non riuscita torno");
        return;
      }
      temp=getWind(1);
      if (temp.length()>1){
        Serial.print("&winddir=");
        Serial.print(temp);
        scrivimem(temp,40);
      }
      temp=getWind(0);
      if (temp.length()>2){
        Serial.print("&windspeedmph=");
        Serial.print(temp);
       scrivimem(temp,60);
      }
      temp=getTemp(0);
      if (temp.length()>3){
        Serial.print("&tempf=");
        Serial.print(temp);
        scrivimem(temp,80);
      }
      temp=getRain(1);
      if (temp.length()>2){
        Serial.print("&rainin=");
        Serial.print(temp);
        scrivimem(temp,100);
      }
      temp=getRain(0);
      if (temp.length()>2){
        Serial.print("&dailyrainin=");
        Serial.print(temp);
        scrivimem(temp,120);
      }
      temp=getHum(0);
      if (temp.length()>1){
        Serial.print("&humidity=");
        Serial.print(temp);
        scrivimem(temp,140);
      }
      temp=getDew();
      if (temp.length()>1){
        Serial.print("&dewptf=");
        Serial.print(temp);
        scrivimem(temp,160);
      }
      temp=getPress(0);
      if (temp.length()>1){
        Serial.print("&baromin=");
        Serial.print(temp);
        scrivimem(temp,180);
      }
}

void pubbws(){
      String temp =leggimem(0);
      String temp1=leggimem(20);
      if ((temp.length()>6) && (temp1.length()>4)){
        Serial.print("ID=");
        Serial.print(id);
        Serial.print("&PASSWORD=");
        Serial.print(PASSWORD);
        Serial.print("&dateutc=");
        Serial.print(temp);
        Serial.print("+");
        Serial.print(temp1);
        client.print("ID=");
        client.print(id);
        client.print("&PASSWORD=");
        client.print(PASSWORD);
        client.print("&dateutc=");
        client.print(temp);
        client.print("+");
        client.print(temp1);
      }
      else
      {
        Serial.println("Lettura data/ora non riuscita torno");
        return;
      }
      temp=leggimem(40);
      if (temp.length()>1){
        Serial.print("&winddir=");
        Serial.print(temp);    

        client.print("&winddir=");
        client.print(temp);
      }    

      temp=leggimem(60);
      if (temp.length()>2){
        Serial.print("&windspeedmph=");
        Serial.print(temp);        

        client.print("&windspeedmph=");
        client.print(temp);
      }   

      temp=leggimem(80);
      if (temp.length()>3){
        Serial.print("&tempf=");
        Serial.print(temp);

        client.print("&tempf=");
        client.print(temp);
      }   

      temp=leggimem(100);
      if (temp.length()>2){
        Serial.print("&rainin=");
        Serial.print(temp);       

        client.print("&rainin=");
        client.print(temp);
      }   

      temp=leggimem(120);
      if (temp.length()>2){
        Serial.print("&dailyrainin=");
        Serial.print(temp);       

        client.print("&dailyrainin=");
        client.print(temp);
      }   

      temp=leggimem(140);
      if (temp.length()>1){
        Serial.print("&humidity=");
        Serial.print(temp);        

        client.print("&humidity=");
        client.print(temp);
      }   

      temp=leggimem(160);
      if (temp.length()>1){
        Serial.print("&dewptf=");
        Serial.print(temp);        

        client.print("&dewptf=");
        client.print(temp);        

      }   

      temp=leggimem(180);
      if (temp.length()>1){
        Serial.print("&baromin=");
        Serial.print(temp);        

        client.print("&baromin=");
        client.print(temp);        

      } 

        Serial.print("&windgustmph=0.00");
        client.print("&windgustmph=0.00");
        Serial.print("&action=updateraw");
        client.print("&action=updateraw");

}

void scrivimem(String dataStr, int pos){

  for (int i=0; i<dataStr.length();i++)
  {
    EEPROM.write((pos+i),dataStr[i]);
  }
  EEPROM.write((pos+dataStr.length()),'#');
  for (int i=pos;i<(pos+50);i++)
  {
    if (EEPROM.read(i)=='#')
    {
      break;
    }
  }

}

String leggimem(int pos){
  int lung=0;
  char dataStr[15];

  for (int i=0;i<15;i++)
  {
    dataStr[i]=0;
  }
  for (int i=pos;i<(pos+20);i++)
  {
    lung++;
    if (EEPROM.read(i)=='#')
    {
      break;
    }
    char c=EEPROM.read(i);
    dataStr[i-pos]=(c); 

  }
  dataStr[lung]='\0';
  return(dataStr);
}

String Leggi (int mem[]) {
    String inString;
    char inChar [3];
    int incomingByte=0;      // a variable to read incoming serial data into
    int time=0;
    String chk;
     while ((incomingByte!=2) && (time<20)){
          time++;
          mySerial.print(byte(06));
          delay(20); 

            if ((mySerial.available() > 0) && (time<20)) {
              delay(30);
              time++;
              incomingByte = mySerial.read();
              inString.concat(incomingByte);
            }
      }

     inString="";
     time=0;
     inString.concat("00"); //aggiungo due cifre
     mySerial.flush();
     if (time>18){
          return("0\0");
     }  

      for (int i=0; i<2; i++){

          if (inString.length()>8){
            chk=(inString.substring(4,8));
          }
          inString="";
          inString.concat("00"); //aggiungo due cifre
          for (int tmp=0; tmp<5; tmp++){
            mySerial.print(byte(mem[tmp]));
            while ((mySerial.available() == 0) && (time<100)){
             delay(30);
             time++;
            }
            if (time>98){
              return("0\0");
              break;  

            }        

            if (mySerial.available() > 0) {
              incomingByte = mySerial.read();
            }

            time=0;
           //delay(200);
               while ((mySerial.available() > 0) && time<200 ) {
                    time++;
                    delay(20);
                    incomingByte = mySerial.read();
                    if (tmp<4){
                      if (tmp!=((incomingByte & B11110000)/B10000)){
                          return("0\0");
                          break;
                      }
                    }
                    if (tmp==4){
                      sprintf(inChar, "%02X", incomingByte);
                      inString.concat(inChar);
                    }
               }
           }

      }
        if (chk!=(inString.substring(4,8)))
        {
          return("0\0");

        }
        inString=inString.trim();
        if (inString.length()>16){
          inString=(inString.substring(0,15));
        }
        return(inString);
}

String getTime(){

      String dataStr="";
      int my_array[] = {0x82,0x8A,0x82,0x82,0xDA};  //0200
      String inString;

        for (int ritenta=0; ritenta<10; ritenta++){
           dataStr="";
            inString=Leggi(my_array);
            if (inString.length()>5){
                //data= inString.substring(4,6);  //estraggo i decimali della temperatura
                dataStr.concat(inString.substring(6,8));  //estraggo l'ora
                dataStr.concat(":");
                dataStr.concat(inString.substring(4,6));  //estraggo i minuti
                dataStr.concat(":");
                dataStr.concat(inString.substring(2,4));  //estraggo i secondi
                if (((inString.substring(6,8))<23 && (inString.substring(6,8))>=0)&&((inString.substring(4,6))<60 && (inString.substring(4,6))>=0) && ((inString.substring(2,4))<60 && (inString.substring(2,4))>=0)) {
                    break;
                }
                else {
                  dataStr="";
                }

             }
             else
             {
                 delay(500);
             }
        }
      return(dataStr);
}

String getDay(){
      String inString;
      String dataStr="";
      int my_array[] = {0x82,0x8A,0x8E,0xAE,0xEE};
        for (int ritenta=0; ritenta<10; ritenta++){
            dataStr="";
            inString=Leggi(my_array);
            if (inString.length()>5){
                dataStr.concat("20");
                dataStr.concat(inString.charAt(13));
                dataStr.concat(inString.charAt(10));
                dataStr.concat("-");
                dataStr.concat(inString.charAt(11));
                dataStr.concat(inString.charAt(8));
                dataStr.concat("-");
                dataStr.concat(inString.charAt(9));
                dataStr.concat(inString.charAt(6));
                if (((inString[13]<='9' && inString[13]>='0')&&(inString[10]<='9' && inString[10]>='0')) && ((inString[11]<='1' && inString[11]>='0')&&(inString[8]<='9' && inString[8]>='0')) && ((inString[9]<='3' && inString[9]>='0')&&(inString[6]<='9' && inString[6]>='0'))) {
                    break;
                }
                else {
                  dataStr="";
                }
           }
           else
           {
               delay(500);
           }
        }
      return(dataStr);
}

String getTemp(int dato){
      String inString;
      String dataStr="";
      //String dataStr;
      char cdata [10];
      int lung=0;
      char buff[10];
      int my_array[6];

      if (dato==1){
        my_array[0] = (0x82);
        my_array[1] = (0x8E);
        my_array[2] = (0x92);
        my_array[3] = (0x9A);
        my_array[4] = (0xFA);
      }
       else
      {
        my_array[0] = (0x82);
        my_array[1] = (0x8E);
        my_array[2] = (0x9E);
        my_array[3] = (0x8E);
        my_array[4] = (0xFA);
      }
        for (int ritenta=0; ritenta<10; ritenta++){
            dataStr="";
            inString=Leggi(my_array);
            if (inString.length()>5){
                (inString.substring(4,6)).toCharArray(buff,3);
                dataStr.concat((atoi(buff))-30);
                dataStr.concat(".");
                dataStr.concat(inString.substring(2,4));  //estraggo le decine e unità della temperatura
               if (((inString[4]<='9' && inString[4]>='0')&&(inString[5]<='9' && inString[5]>='0')) && ((inString[2]<='9' && inString[2]>='0')&&(inString[3]<='9' && inString[3]>='0'))) {
                   break;
                }
                else {
                  dataStr="";
                }
           }
           else
           {
              delay(500);
           }
        }
      if (dataStr.length()>2)
      {

        dataStr.toCharArray(cdata, dataStr.length()+1);
          float fdata=(atof(cdata)*1.800+32.000);
          if (fdata<1000){lung=7;}
          if (fdata<100){lung=6;}
          if (fdata<10){lung=5;}
          dtostrf(fdata,lung,3,cdata);
          dataStr=cdata;
      }
      else
      {
        dataStr="";
      }

      return(dataStr);
}

String getHum(int dato){
      String dataStr="";
      String inString;
      int my_array[6];
      if (dato==1){
        my_array[0] = (0x82);
        my_array[1] = (0x8E);
        my_array[2] = (0xBE);
        my_array[3] = (0xAE);
        my_array[4] = (0xDA);
      }
       else
      {
        my_array[0] = (0x82);
        my_array[1] = (0x92);
        my_array[2] = (0x86);
        my_array[3] = (0xA6);
        my_array[4] = (0xDA);
      }
        for (int ritenta=0; ritenta<10; ritenta++){
            dataStr="";
            inString=Leggi(my_array);
            if (inString.length()>5){
                dataStr.concat(inString.substring(2,4));  //estraggo le decine e unità della temperatura
               if ((inString[2]<='9' && inString[2]>='0')&&(inString[3]<='9' && inString[3]>='0')) {
                   break;
                }
                else {
                  dataStr="";
                }
           }
           else
           {
               delay(500);
           }
        }
      return(dataStr);
}

String getPress(int dato){
      String dataStr="";
      String inString;
      int my_array[6];
      if (dato==1){
        my_array[0] = (0x82);
        my_array[1] = (0x96);
        my_array[2] = (0xBA);
        my_array[3] = (0x8A);
        my_array[4] = (0xD6);
      }
       else
      {
        my_array[0] = (0x82);      //press hg
        my_array[1] = (0x96);
        my_array[2] = (0xB6);
        my_array[3] = (0xB6);
        my_array[4] = (0xD6);
      } 

        for (int ritenta=0; ritenta<10; ritenta++){
            dataStr="";
            inString=Leggi(my_array);
            if (inString.length()>5){
                dataStr.concat(inString.charAt(7));
                dataStr.concat(inString.charAt(4));
                dataStr.concat(inString.charAt(5));
                if (dato==1){
                  dataStr.concat(inString.charAt(2));
                  dataStr.concat(".");
                  dataStr.concat(inString.charAt(3));
                }
                else
                {
                  dataStr.concat(".");
                  dataStr.concat(inString.charAt(2));
                  dataStr.concat(inString.charAt(3));
                }

                if ((inString[7]<='9' && inString[7]>='0')&&(inString[4]<='9' && inString[4]>='0') && (inString[5]<='9' && inString[5]>='0')&&(inString[2]<='9' && inString[2]>='0') && (inString[2]<='9' && inString[2]>='0')) {
                  break;
                }
                else {
                  dataStr="";
                }
           }
           else
           {
              delay(500);
           }
        }
      return(dataStr);

}

String getWind(int dato){
      String dataStr="";
      char cdata [10];
      int lung=0;
      String inString;
      char buff[10];
      int my_array[] = {0x82,0x96,0x8A,0x9E,0xF2};
        for (int ritenta=0; ritenta<10; ritenta++){
            dataStr="";
            inString=Leggi(my_array);
            if (inString.length()>5){
              if (dato==0){
                 dataStr.concat(inString.charAt(7));
                 buff[0]=inString[4];
                 buff[1]=inString[5];
                 int tmp=(strtol(buff,NULL,16));
                 if (tmp<=9){
                   dataStr.concat("0");
                 }

                 dataStr.concat(tmp); // converts a HEX string to long
                 dataStr.concat(dataStr.charAt(2));
                 dataStr.setCharAt(2, '.');
                if ((inString[4]<='9' && inString[4]>='0')&&(inString[5]<='9' && inString[5]>='0')) {
                  break;
                }
                else {
                  dataStr="";
                }
              }
              else
              {
                 buff[0]=inString[6];
                 buff[1]=0;
                 int tmp=((strtol(buff,NULL,16))*22.5);
                 dataStr.concat(tmp);
                if ((tmp>=0)&&(tmp<=360)) {
                  break;
                }
                else {
                  dataStr="";
                  ritenta=0;
                }
              }
           }
           else
           {
               delay(500);
           }
        }

      if (dato==0){    //se richiedo la velocità convertoin miglia orarie    

           if (dataStr.length()>2)
           {
                  dataStr.toCharArray(cdata, (dataStr.length()+1));
                  float fdata=(atof(cdata)*2.23);
                  if (fdata<1000){lung=6;}
                  if (fdata<100){lung=5;}
                  if (fdata<10){lung=4;}
                  dtostrf(fdata,lung,2,cdata);
                  dataStr=cdata;
          }
          else
          {
            dataStr="";
          }
      }

      return(dataStr);
}

String getRain(int dato){
       String dataStr="";
      char cdata [10];
      int lung=0;
      String inString;
            int my_array[6];
      if (dato==1){      //pioggia 1 ora
        my_array[0] = (0x82);
        my_array[1] = (0x92);
        my_array[2] = (0xAE);
        my_array[3] = (0x92);
        my_array[4] = (0xDA);
      }
       else
      {
        my_array[0] = (0x82);      //0497
        my_array[1] = (0x96);
        my_array[2] = (0xA6);
        my_array[3] = (0x9E);
        my_array[4] = (0xD6);
      }
        for (int ritenta=0; ritenta<10; ritenta++){
            dataStr="";
            inString=Leggi(my_array);
            if (inString.length()>5){
                dataStr.concat(inString.substring(6,8));
                dataStr.concat(inString.substring(4,6));
                if ((inString[6]<='9' && inString[6]>='0')&&(inString[7]<='9' && inString[7]>='0') && (inString[4]<='9' && inString[4]>='0')&&(inString[5]<='9' && inString[5]>='0') && (inString[2]<='9' && inString[2]>='0')&& (inString[3]<='9' && inString[3]>='0')) {
                  break;
                }
                else {
                  dataStr="";
                }
           }
           else
           {
               delay(500);
           }
        }

         if (dataStr.length()>2)
      {  

          dataStr.toCharArray(cdata, (dataStr.length()+1));
            //Serial.print("cdata ");
            //Serial.println(cdata);
          float fdata=(atof(cdata)*2.54);  //in pollici
          if (fdata<1000){lung=6;}
          if (fdata<100){lung=5;}
          if (fdata<10){lung=4;}
          dtostrf(fdata,lung,2,cdata);
          dataStr=cdata;
      }
      else
      {
        dataStr="";
      }

      return(dataStr);
}

String getDew(){

      String inString;
      String dataStr="";
      char cdata [10];
      int lung=0;
      char buff[10];

      //Serial.println("leggo pioggia 1h ");
      int my_array[] = {0x82,0x8E,0xB2,0xBA,0xFA};
        for (int ritenta=0; ritenta<10; ritenta++){
            dataStr="";
            inString=Leggi(my_array);
            if (inString.length()>5){            

                (inString.substring(4,6)).toCharArray(buff,3);
                dataStr.concat((atoi(buff))-30);
                dataStr.concat(".");
                dataStr.concat(inString.substring(2,4));  //estraggo le decine e unità della temperatura
               if (((inString[4]<='9' && inString[4]>='0')&&(inString[5]<='9' && inString[5]>='0')) && ((inString[2]<='9' && inString[2]>='0')&&(inString[3]<='9' && inString[3]>='0'))) {
                   break;
                }
                else {
                  dataStr="";
                }
           }
           else
           {
              delay(500);
           }
        }

      if (dataStr.length()>2)
      {

          dataStr.toCharArray(cdata, dataStr.length()+1);
          float fdata=(atof(cdata)*1.800+32.000);
            if (fdata<1000){lung=7;}
            if (fdata<100){lung=6;}
            if (fdata<10){lung=5;}
            dtostrf(fdata,lung,3,cdata);

          dataStr=cdata;
            }
      else
      {
        dataStr="";
      }

      return(dataStr);
}
For the connection we uses the serial port pins 2 and 3 of module Arduino for this reason we have used the library NewSoftSerial that lets you emulate a UART using the generic contact I/O such as serial lines.
Periodically, the Arduino microcontroller polls the weather station and stores the data for the date, time, outside temperature, outside humidity, wind speed and direction, rain fell in one hour and 24 hours, the atmospheric pressure and dew point. The constant UPDATE_INTERVAL defines after how many seconds Arduino public the data collected on the site www.wunderground.com.
In order to publish the data of the control unit on this site, as already mentioned, you must have an account, once registered, there is assigned an ID that will be introduced during the connection to the site in order to proceed with publication.
In the sketch for the Arduino you must enter your ID and password, so that the publication will be successful, otherwise our system will point to the site but will not get access.
For the publication of data is sufficient to recall the page http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php,
passing data to the URL. For example, you have to compose a string like this:
http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?ID=KCASANFR5&PASSWORD=XXXXXX&dateutc=2000-01-01+10&winddir=230&windspeedmph=12&windgustmph=12&tempf=70&rainin=0&baromin=29.1&dewptf=68.2&humidity=90&weather=&clouds=&softwaretype=vws%20versionxx&action=updateraw.
As you see, the user ID and password are inserted in the string. The data temperature should be expressed in Fahrenheit degrees and the wind speed must be in mph (miles per hour). The conversion of the data read by the control unit is made directly from the sketch, so as to spare you the burden to proceed with the manual calculation.
The use of the site www.wunderground.com for the publication of meteorological data is free and subject only to the rules of the provider, there are also advanced features, including the addition of photos and images from a webcam filming on location is the weather station and sent through the Internet.

Tuesday, March 13, 2012

REAL TIME ENERGY MONITOR WITH ARDUINO


This is a simple power meter to analize the current consuming in a house using the led indicator of a house energy meter.
Reading the red led of a home energy counters the system detects the corrent consumption in a house.
It is a noninvasive method, not cut wire, no current disconnects, so a very interesting method…
The system consists of two parts: the Arduino board that detects the led pulses and sends the data via the XBee module, and a PC that recive the data through a USB/Xbee module and processes the data with LabVIEW so you can prepare and study the consumption in a very instant.
Arduino sends two datas to the PC:
1 – Real time datas
2 – Average consumption measured in a time of 5 minutes.


From the picture we see that the LED that indicates the current consumption is the red LED near to the display. In particular is the LED superior.
Arduino module
To detect the LED blinking you have to apply a simple photoresistor above the led and covered it with black tape. To read the analog voltage using the Arduino you have to use a resistive divider as shown in diagram:
The LED blinking causes the voltage drop down and this value is read by Arduino and compared with the voltage acquired by the potentiometer connected in the channel A0. This potentiometer has the task to adjust the sensitivity threshold.
The read data are processed from the sketch and then sends to the PC via Xbee module.
The Arduino code acquisition is as follows:
 
   delay(10); //10ms
   val_pot = analogRead(POT);   
   delay(10); //10ms
   val_sensore = analogRead(SENSORE);
  if((val_sensore > val_pot)&(flag_acquire == 0)){ 
      flag_acquire = 1;
      digitalWrite(LED, LOW);
With this code Arduino acquires the two voltages, the photoresistor voltage compared with the voltage of the potentiometer, if the value is greater than the sketch actives the flag “flag_acquire = 1″, then read how much time has passed to another flash.
To do this use arduino to read a statement in an internal counter that returns the milliseconds since power on. The instruction is “millis ()” code here:
pre_tmS = cur_tmS;
      cur_tmS = millis();
      if( cur_tmS > pre_tmS ) {
        tm_diffS = cur_tmS – pre_tmS;
     }
There are 2 variables pre_tmS and cur_tmS, “cur_tmS” needs to read the current value of the internal counter: cur_tmS = millis (); Then if the condition (cur_tmS> pre_tmS) is true, I note the elapsed time between cycles, ie between the LED ON and the next cycle of the LED ON and write it on the variable “pre_tmS”. Now we have to send to the PC via the serial port using XBee with these instructions:
Serial.print(“S”); 
      Serial.println(tm_diffS); 
     delay(10); //10ms
First Arduino sends a marker “S” used to labview to recognize that this value is part of the reading that real-time instant, then send the value in milliseconds elapsed. Now you have to reset the flag when the LED goes OFF using this statement:
  if((val_sensore < val_pot)&(flag_acquire == 1)){ 
      flag_acquire = 0;
     digitalWrite(LED, HIGH);
      impulsi++;         
      delay(10); //10ms 
  }
You have to check the voltage acquired by the sensor, if it falls below the potentiometer value and the flag is active “flag_acquire == 1″ then you have to reset the flag. Note that the statement “impulsi++;” is simply a counter that counts the cycles of the LED power meter, this is to make an average energy consumed every 5 minutes. The third task is similar to the first task, wait 1 second, and increments the counter “time_flag++,” which is the fourth task of counting 300secondi (5 minutes). In addition, this task blinks the LED connected to pin 12 at a rate of 1 second.
The fourth task as mentioned above waiting 5 minutes and then sent via serial marker “L” is used to program labview to recognize that the data sent is the data on the average found in 5 minutes.

The sketch

#define POT 0
#define SENSORE 1
#define LED 13
#define LED1sec 12

// definire il tempo casuale che varia tra 40ms e 250ms
#define TimeAcquire  1000      //1sec
#define Time5Minuts  300      //5 minuti = 300sec 

unsigned long cur_tm = millis();
unsigned long pre_tm = cur_tm;
unsigned int tm_diff = 0;  

unsigned long cur_tmS = millis();
unsigned long pre_tmS = cur_tmS;
unsigned int tm_diffS = 0;  

unsigned int time_flag=0;

unsigned int impulsi=0;
unsigned int val_pot=0;
unsigned int val_sensore=0;
char flag_acquire=0;
char flag_time=0;

void setup() {  

  pinMode(LED, OUTPUT);
  pinMode(LED1sec, OUTPUT);
  Serial.begin(115200);          //  setup serial 115200
  Serial.println("ENEL KW/h reader!");

}  

void loop() {

  //Acquisisco
   delay(10); //10ms
   val_pot = analogRead(POT);    // read the input pin
   delay(10); //10ms
   val_sensore = analogRead(SENSORE);    // read the input pin

  if((val_sensore > val_pot)&(flag_acquire == 0)){
      flag_acquire = 1;
      digitalWrite(LED, LOW);

      pre_tmS = cur_tmS;
      cur_tmS = millis();
      if( cur_tmS > pre_tmS ) {
        tm_diffS = cur_tmS - pre_tmS;
      }
      Serial.print("S");
      Serial.println(tm_diffS);  

      delay(10); //10ms

  }
  if((val_sensore < val_pot)&(flag_acquire == 1)){
      flag_acquire = 0;
      digitalWrite(LED, HIGH);
      impulsi++;          //Incrementa impulsi
      delay(10); //10ms
  }

  //------Ogni 5 minuti invia "impulsi" ----------
  pre_tm = cur_tm;
  cur_tm = millis();
  if( cur_tm > pre_tm ) {
    tm_diff += cur_tm - pre_tm; //+=
  }
  if( tm_diff >= TimeAcquire ) { //Task ogni secondo
    tm_diff = 0;

    time_flag++;

    if(flag_time==0){
      digitalWrite(LED1sec, HIGH);
      flag_time = 1;
    }else{
      digitalWrite(LED1sec, LOW);
      flag_time = 0;
    }

  }

  if(time_flag>=Time5Minuts){
//Sono passati 5 minuti ? ..... Invia "impulsi" rilevati dal contatore
      Serial.print("L");
      Serial.println(impulsi);
      impulsi = 0;
      time_flag = 0;
  }

 //--------------------------------------------------

}
LABVIEW interface
To recive the data we use the XBee UartSbee V3.1 module from Futura Elettronica.

The interface created in LabVIEW is simple to use:
As can be seen from this figure, the top graph shows the average consumption every 5 minutes, while the bottom graph shows the real-time energy consumption. It ‘can save the data using the device as a data logger.