Arduino Ethernet and Pachube: remote sensors & web-control

Below are a couple of sketches for Arduino Ethernet: the first can be used to share sensor data with Pachube and grab remote sensor data, so you can effectively have both "local" and "remote" sensors; and the second enables you to control Arduino Ethernet via a web page.

These sketches should make Arduino-based web-controlled home automation, and remote-responsive spaces a lot easier. The advantage of working with an ethernet shield is that you no longer need to tether the Arduino to a computer in order to access Pachube and other network services!

Arduino Ethernet with Pachube Arduino Ethernet with Pachube Arduino Ethernet with Pachube

These are coded for the official Arduino Ethernet shield. We've had better, more consistent, results with this shield than others that are available; we also find it easier to work with and code for so we'll generally be developing examples using this shield from now.

Update: May 13 2009

The code for these two examples has just been updated to account for some changes in the way Pachube returns HTTP headers, to fix a timer overflow problem and to add a User-Agent header identifying the Arduino as such.

This code has been tested with Arduino Diecimila and Arduino 14. Note that this code does not work with Arduino 15 - there seems to be a RAM problem that we haven't tracked down yet. Also, the Arduino Mega does not currently work with the ethernet shield out-of-the-box without the hack listed here: http://mcukits.com/2009/04/06/arduino-ethernet-shield-mega-hack/

If you insist on using Arduino 12 or 13, you will have to make use of two little changes to the Ethernet library, detailed here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1226426240/15 (enabled use of pins 8 & 9) and here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1227978344 (repeated TCP connections).


A. Arduino Ethernet with Pachube inputs and outputs

The first sketch enables an Arduino Ethernet both to share input sensor data with and grab output data from Pachube. Essentially, it means that you can share your local sensor data with others and also use remote sensor data in your Arduino sketch. There is a single function called at the beginning of every loop: pachube_in_out() takes care of all Pachube functions necessary, including repeated updating data at a more or less fixed interval. You can then make use of the remote variables as necessary in the rest of the loop.

  1. First, create a new Pachube manual feed. Fill in the info and tags if you like (and if you know what you're doing), but it's not necessary at this stage.
  2. Then, download the Arduino Ethernet Pachube Input Output code.
  3. You'll need to make a few little configuration changes:
    #define SHARE_FEED_ID              1872    
    #define REMOTE_FEED_ID             256     
    #define REMOTE_FEED_DATASTREAMS    4      
    #define UPDATE_INTERVAL            10000
    #define RESET_INTERVAL             10000

    #define PACHUBE_API_KEY            "ENTER_YOUR_API_KEY_HERE"

    byte mac[] = { 0xCC, 0xAC, 0xBE, 0xEF, 0xFE, 0x91 };
    byte ip[] = { 192, 168, 0, 144   };   
    byte remoteServer[] = { 209,40,205,190 };  
    • Replace SHARE_FEED_ID with the new manual feed ID you set up in step 1
    • REMOTE_FEED_ID is the ID of the remote feed whose sensors you want to access. As downloaded the sketch works with any remote feed that has floats/integers for datastreams; however it could easily be edited to account for other types of datastream variable.
    • Make sure to set REMOTE_FEED_DATASTREAMS to equal the number of datastreams of the remote feed you're connecting to.
    • Paste in your API key
    • You probably don't need to change the update and reset interval; certainly there's no point in making it less than 5 seconds since Pachube will ignore more frequent updates during the beta period.
    • Finally, set your Mac address and IP address as normal with this shield.
  4. You can now edit your own code within loop() as below, and it should keep running only occasionally pausing when pachube_in_out() needs to do something intensive (like read/write to the Ethernet shield, or reset it when there's a problem). For example you might want to analogWrite to a pin at a level proportional to a remote sensor (which could make a nice indicator of sorts).

    void loop()
    {
      pachube_in_out();
     
      // then put your code here, you can access remote sensor values
      // by using the remoteSensor float array, e.g.:  
      analogWrite(3, (int)remoteSensor[3] * 10); // remoteSensor is a float
      analogWrite(5, (int)remoteSensor[1]);

      // you can have code that is time sensitive (e.g. using 'delay'), but
      // be aware that it will be affected by a short pause during connecting
      // to and reading from ethernet (approx. 0.5 to 1 sec).
      // e.g. this code should carry on flashing regularly, with brief pauses
      // every few seconds during Pachube update.

      digitalWrite(6, HIGH);
      delay(100);
      digitalWrite(6, LOW);
      delay(100);

    }

  5. Finally, upload the code to the Arduino, and make sure it's plugged in to the network, and connect up your sensors and actuators!

    No fussing around with routers and port-forwarding because this is making a manual PUT update, so it should work fine behind a firewall.

    Go and have a look at your feed's Pachube page, and, unless you changed anything in the original downloaded code, the feed should look something like this: http://www.pachube.com/feeds/1872, where the first 6 datastreams are for the Analog-in 0 to 5 values, and the last two datastreams show the number of successful updates to Pachube, and the number of failed attempts to update Pachube (I've noticed around a 3 to 5% failure rate after long periods).

    Edit the feed to set tags for the datastreams as necessary, and then let others know about your newly connected Arduino Ethernet, so they too can connect to it remotely!


B. Remote Control Arduino Ethernet via web page

This sketch, built on the previous code, enables an Arduino Ethernet using Pachube to be controlled remotely via a web page, while also sharing your sensor data with Pachube.

There are of course a number of methods out there for controlling Arduino ethernet via web forms. However, the advantage of using Pachube for control is that:

  1. Pachube's password-protection makes it more secure.
  2. You can either use our web page to update your feed or you can copy-paste the HTML into your own webpage, though either way you don't need to install any code on your own server (e.g. php, etc.)
  3. You don't need to run a server on the Arduino (and don't need to worry about firewalls, port forwarding etc.) which can sometimes be difficult to sustain (and troubleshoot).
  4. You get all those other useful Pachube features (graphs, history tracking etc.)
  5. You can easily build multiple arduino ethernet entities that are all controlled by a single web page.

Here are the steps for controlling your Arduino Ethernet from a web page:

  1. First, create TWO new Pachube manual feeds, one to act as a "control" feed, and the other to share your Arduino sensor data. Fill in the info if you like (and if you know what you're doing), but it's not necessary at this stage.
  2. Then, download the Arduino Ethernet Pachube Controller code.
  3. You'll need to make a few little configuration changes:
    #define SHARE_FEED_ID              1872    
    #define CONTROL_FEED_ID            1260     
    #define UPDATE_INTERVAL            10000
    #define RESET_INTERVAL             10000  

    #define PACHUBE_API_KEY            "ENTER_YOUR_API_KEY_HERE"

    byte mac[] = { 0xCC, 0xAC, 0xBE, 0xEF, 0xFE, 0x91 };
    byte ip[] = { 192, 168, 0, 143   };
    byte remoteServer[] = { 209,40,205,190 };
    • Replace SHARE_FEED_ID with the new manual feed you set up in step 1 to share your sensor data.
    • CONTROL_FEED_ID is the ID of controller feed.
    • Paste in your API key.
    • This time you don't have to set REQUEST_FEED_DATASTREAMS because we are assuming it only has one datastream.
    • Again, you probably don't need to change the update and reset interval; certainly there's no point in making it less than 5 seconds since Pachube will ignore more frequent updates during the beta period.
    • Finally, set your Mac address and IP address as normal with this shield.
  4. As before, upload the code to the Arduino, and make sure it's plugged in to the network, and again, there's no fussing around with routers and port-forwarding because this is making a manual PUT update, so it should work fine behind a firewall. Connect up your sensors and actuators -- and if you're using LEDs you should probably use current limiting resistors unlike the demo photos above!
  5. Now go to the Arduino Ethernet controller web page, located here: http://community.pachube.com/files/arduino_controller.html and do the following:
    • Enter the controller feed ID, and click "authorise feed" - you'll probably need to enter your Pachube login and password.
    • Tick digital output boxes to switch them on or off; enter values in the PWM boxes, followed by a click on "update values" to send the update. Note that, if you didn't edit the Arduino code, then pins 0 and 1 are used for Serial communication and so are unusable in this sketch. To enable them, edit the Arduino sketch to remove all Serial code.
    • Keep changing values as often as you like... Switch things on and off, set PWM values up and down, whatever.

    The HTML page updates Pachube via a POST form (which simulates an HTTP PUT request by appending "_method=put" to the action URL).

  6. Bookmark the controller web page, so that you can return to it. Alternatively, download the source code and copy-paste into your own webpage -- since it's based on HTML forms, there will be no cross-domain security issues.

Let me know how you get on!

AttachmentSize
arduino_controller.html5.32 KB
ethernet_Pachube_controller_1_1.zip4.48 KB
ethernet_Pachube_input_output_1_1.zip4.58 KB

Re: Arduino Ethernet and Pachube: remote sensors & web-control

we are going to work on arduino + pachube on the hackup day in milano: http://www.hack-up.org/wiki/index.php?title=Milan_18_Jan_2009

I'll keep you updated

Re: remote control Arduino Ethernet via web page

hi,
i am tryin to use this project, remote control Arduino Ethernet via web page, i am using Arduino 0016, hardware is Arduino Duemilanove with ATMega 328. I dont get any error but when i open pachube controller page and turn on all the LEDS, i dont see the LED on my board being turned on. i dont know what is happening,

someone please help

Re: Arduino Ethernet and Pachube: remote sensors & web-control

the best thing to do is to put in some Serial.println statements to debug what's actually happening and how far it's getting.

one thing to point out: as it says above, "This code has been tested with Arduino Diecimila and Arduino 14" so ymmv.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Hello
Im really new to this, but im loving it already ;)
How can I use this with the arduino pluged in the USB, ?
I read in the blog it should work??
how ?
tnx

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Hi Mako
You would be best off using the tutorials listed under "Arduino + computer" http://community.pachube.com/node/212

The simplest thing to use is Pachuino: http://community.pachube.com/node/13 which is a library for Processing that connects a USB-connected Arduino directly to Pachube for both inputs and outputs.

changing code to work with my computer-Please help!!

Hello I am new to all this. In the above tutorial "A. Arduino Ethernet with Pachube inputs and outputs" I followed every step... I think.
To my understanding you can copy and paste the code given in the tutorial to the arduino. I then changed the share feed to the one I created and changed the api key to the one given to me. I then changed the the mac address to the mac address of my computer. I then tried to upload it to the arduino and got an error in my mac address.

To my understanding the use of this given program is to be able to upload the program, with inserted sensory code I have created placed into the proper spot in that program, plug in an ethernet cable into the wall, and then plug the ethernet cable into the ethernet shield and wa la! it works. If this is accomplished, I will then be able log on to pachube and see the data from the arduino. Keep in note i assume that after the program is uploaded I can detatch the arduino from my computer and leave just the arduino and ethernet sheild plugged into the wall.

I hope that this is what this tutorial is for. Because this is what I need to accomplish.
-thanks! Please help though I just need to know basically how to write the code, to accomplish what I have written above.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

A couple of things:

1. You'll need to download the code, not just copy paste from section A (there is more to the code than that which is explained in the tutorial -- but the rest of it shouldn't require any changes).

2. Your MAC address has to be unique on your network, it SHOULD NOT be the same as your computer's, that's why you're getting an error. If in doubt try this: { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; -- it's the one often used in the arduino tutorials, that you will find here: http://arduino.cc/en/Reference/Ethernet

Let us know how you get on.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Hello, I guess I am very confused in step 2 from section A, it says download the Arduino Ethernet Pachube Input Output code, but where do I down load it to? I have looked at the code from one of the many folders that got downloaded-it all seems to be the code in each different folder, each of those folders has the code pasted below: of course with the share feed and api changes made. Is there more than this?, if there is, is there a place I can go copy the code and paste it into an arduino sketch, and upload it to the arduino? Thanks, I must apologize, I'm very, very new to all this, I appreciate what help I can get
/* ==============================
* This code, which assumes you're using the official Arduino Ethernet shield,
* updates a Pachube feed with your analog-in values and grabs values from a Pachube
* feed - basically it enables you to have both "local" and "remote" sensors.
*
* Tested with Arduino 14
*
* Pachube is www.pachube.com - connect, tag and share real time sensor data
* code by usman (www.haque.co.uk), may 2009
* copy, distribute, whatever, as you like.
*
* v1.1 - added User-Agent & fixed HTTP parser for new Pachube headers
* and check millis() for when it wraps around
*
* =============================== */

#include
#include

#undef int() // needed by arduino 0011 to allow use of stdio
#include // for function sprintf

#define SHARE_FEED_ID 1872 // this is your Pachube feed ID that you want to share to
#define REMOTE_FEED_ID 256 // this is the ID of the remote Pachube feed that you want to connect to
#define REMOTE_FEED_DATASTREAMS 4 // make sure that remoteSensor array is big enough to fit all the remote data streams
#define UPDATE_INTERVAL 10000 // if the connection is good wait 10 seconds before updating again - should not be less than 5
#define RESET_INTERVAL 10000 // if connection fails/resets wait 10 seconds before trying again - should not be less than 5

#define PACHUBE_API_KEY "ENTER_YOUR_API_KEY_HERE" // fill in your API key

byte mac[] = { 0xCC, 0xAC, 0xBE, 0xEF, 0xFE, 0x91 }; // make sure this is unique on your network
byte ip[] = { 192, 168, 0, 144 }; // no DHCP so we set our own IP address
byte remoteServer[] = { 209,40,205,190 }; // pachube.com

float remoteSensor[REMOTE_FEED_DATASTREAMS]; // we know that feed 256 has floats - this might need changing for feeds without floats

void setup()
{
Serial.begin(57600);
setupEthernet();

pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}

void loop()
{

// call 'pachube_in_out' at the beginning of the loop, handles timing, requesting
// and reading. use serial monitor to view debug messages

pachube_in_out();

// then put your code here, you can access remote sensor values
// by using the remoteSensor float array, e.g.:

analogWrite(3, (int)remoteSensor[3] * 10); // remoteSensor is a float
analogWrite(5, (int)remoteSensor[1]);

// you can have code that is time sensitive (e.g. using 'delay'), but
// be aware that it will be affected by a short pause during connecting
// to and reading from ethernet (approx. 0.5 to 1 sec).
// e.g. this code should carry on flashing regularly, with brief pauses
// every few seconds during Pachube update.

digitalWrite(6, HIGH);
delay(100);
digitalWrite(6, LOW);
delay(100);

}

Re: Arduino Ethernet and Pachube: remote sensors & web-control

If you download the 'Arduino Ethernet Pachube Input Output' code from the link above you will have one zip file (http://community.pachube.com/files/ethernet_Pachube_input_output_1_1.zip), which, when extracted will give you a folder called 'ethernet_Pachube_input_output_1_1'. Inside that folder are 3 files (pachube_functions.pde, ethernet_functions.pde,ethernet_Pachube_input_output_1_1.pde). It sounds like this is *not* what you're getting which sounds like your zip extraction application is not working correctly.

If you are getting the 3 files inside the folder, then if you load 'ethernet_Pachube_input_output_1_1.pde' in Arduino, it will automatically include the other two files as separate tabs within the Arduino IDE. Compile and upload as normal. You should probably have a look at http://arduino.cc/en/Guide/Environment to get more info about using the Arduino application itself if you are not familiar with using tabs.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Thank you so much for your help!!! The program now compiles and is uploaded to the arduino (with my little sensory program added). Now when I look at the serial port, it says,
"Connecting...
connection failed!2reset ethernet
setup complete"
Now besides setting up my feed (which took about a minute) I have done nothing with it, is this why I am getting the connection failed? Do I need to do something more in the pachube feed so it can read the information from my arduino? Keep in mind, the Ethernet shield is plugged into an Ethernet cable which is then in turn plugged into a live Ethernet jack in the wall. The arduino is not connected to my computer when I did this (except when I read the serial port). Again thank you so much for your help.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Have you got the ethernet shield working at all yet? I.e. have you tried the basic tutorials on the Arduino site, or that come with the ethernet library? Make sure that you actually have it working with the simplest examples first, then you can more easily troubleshoot getting it to work with Pachube. For example, when you say that "the Ethernet shield is plugged into an Ethernet cable which is then in turn plugged into a live Ethernet jack in the wall", it's not clear whether you're trying to plug straight into, say, a corporate or academic network, which might have its own restrictions on network traffic (and requirement for setting up the shield). If you're working from home, then you're more likely to want to plug it into your router.

static and dynamic IP addresses

Hello, me again. I have been looking messing with the code and I was wondering exactly this step ment: " Mac address and IP address as normal with this shield", the mac address I understand, but using the IP address is difficult. I did an "arp -a" on my command module and I see that the IP type is dynamic. Does this mean that I can not use this IP address in the code for step A? I assume so. I also assume that if it was static it would work. Is there a way that using a dynamic IP adress would work? Thanks

Re: Arduino Ethernet and Pachube: remote sensors & web-control

There is a DHCP library available for Arduino: http://blog.jordanterrell.com/post/Arduino-DHCP-Library-Version-04.aspx
However, we don't currently have tutorial code for using that library with the Pachube code used above (we have some code that we've used internally, just haven't had a chance to debug, make generic and comment thoroughly). Shouldn't be too hard to get it working though - if you get some good demo code, please post back here!

Problems completing part B

Hello, thanks for the help from last time. It was just what I needed. With part B, I am not able to do turn on or off an LED-as directed in the tutorial. Below is what the serial port says. I can see in my feed that it is live. so it is "talking to my feed" but when I go to the "remotely control the arduino page" and type in my feed and press authorise,- in the debug box this shows up, "Control http://www.pachube.com/api/feeds/3284.xml live Burlington d=0000000000&a=000000000000", then when I press an analog off or on button, it disappears. But remember when I press the analog on or off it doesn't work on the LED's I got set up. oh, in the value part of my feed it says, "d=0000000000&a=000000000000". I don't know what needs to be done to get these LED's to work as in the tutorial? All this does not mean much too me, as obviously seen before, I'm a very new beginner at all this. Again-thanks for all the help


reset ethernet
setup complete
Connecting...
GET request to retrieve
finished GET now PUT, to update
finished PUT: 929
HTTP/1.1 401 Unauthorized
Server: nginx/0.6.34
Date: Wed, 25 Nov 2009 18:03:47 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
WWW-Authenticate: Basic realm="Web Password"
X-Runtime: 0.00544
Cache-Control: no-cache
Set-Cookie: _pachube_session_id=7c097132d4604dc1fd3e555997d0a609; path=/
Content-Length: 12

UnauthorizedHTTP/1.1 401 Unauthorized
Server: nginx/0.6.34
Date: Wed, 25 Nov 2009 18:03:47 GMT
Content-Type: text/plain; charset=utf-8
Connection: close
WWW-Authenticate: Basic realm="Web Password"
X-Runtime: 0.00247
Cache-Control: no-cache
Set-Cookie: _pachube_session_id=27f982c28609c0821aacd774aac19270; path=/
Content-Length: 12

Unauthorizeddisconnecting.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

(remember when pasting in code to wrap it in "[code-]" and "[-/code]" (without those "-" characters))

If you read through the transcript that you pasted in, it says in several placed "Unauthorized" -- sounds like either you haven't put in your API key into your Arduino code or perhaps you have put in the incorrect API key.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

The other possibility is that you're attempting to retrieve or update to feeds that don't belong to you.

datastream problems

Hello, me again,
Hi, I have a manual feed setup with values from a light sensor. When I go look at the feed, I see all 7 datastreams with data from the sensor, and thusly, the graphs don't really have too many data pionts. How would I have all the data from the light sensor update to one datastream, so I could read them on a graph? Is it something in the programming that I have to change or is it on pachube? Thanks again

Re: Arduino Ethernet and Pachube: remote sensors & web-control

I don't quite follow what problem you're having. Can you give a fuller explanation and include links to your feed?

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Sorry, I don't understand the code, that is why I guess I'm writing this. First, things first, I have a photo resistor, it senses values, then puts these values into an analog in pin. I have the code in Part B of this tutorial. I dont know how to manipulate that code, so that it takes the values from the analog in pin (values put there by the photo resistor) and puts those values into one data stream in my pachube feed. This is a link to my feed, http://www.pachube.com/feeds/3903, as you can see thre are values put into all the data streams. Please note, that without me changing the code whatsoever, the feed will still get values from the arduino, the values in all the data streams (except the las two-obviously) appear to be values coming from the photo resistor-but I'm not sure.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Which pin number is your photo resistor connected to? That is then the Pachube datastream that contains the accurate data. If you are seeing the same values on all the analog-ins that's because, unless you pull all the other pins to ground (i.e. by connecting them directly to ground) then they get noise from the one pin that is connected to something (i.e. your photo resistor) which is why they appear to be seeing the same (or similar) values.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

I'm new to the Arduino and I have several questions about this project. First, I have an Arduino Duemilanove. I don't know if this is an Arduino 14, 15 or what. This project says it was tested with Arduino 14 and has RAM problems with Arduino 15. Will my Duemilanove work with this.

In my project I want to have 4 data streams. First is a pulse (that lasts several minutes) from my gas meter. I want to connect this to a digital input pin and when it's high, it would output to pachube a value of 2409. This is about the number of BTUs consumed for every pulse of my meter. This is the first data stream I want to get running. I'll add the others sensors later, those will be:
Electricity usage - I'll take a current transformer and connect it to one of the analog input pins
Inside temp - thermister connected to analog input pin
Outside temp - thermister connected to analog input pin

For the current and temperatures, I'll need to scale the data so they read in KW and degrees F before I send them to Pachube.

I'm trying to understand how the sketch knows what to output to pachube. It seems to me that this line of code is responsible for creating the CSV text for pachube:
sprintf(pachube_data,"%d,%d,%d,%d,%d,%d,%d,%d",analogRead(0),analogRead(1),analogRead(2),analogRead(3),analogRead(4),analogRead(5), successes + 1, failures);

If that's correct, then it's just reading the values of the 6 analog pins and sending this to pachube. Is that correct?
It seems to me I would need to change it to something like:

sprintf(pachube_data,"%d,%d,%d,%d,%d,%d",GasMeterBTU,CurrentAmps,TempIn,TempOut, successes + 1, failures);

In the ethernet_Pachube_input_output_1_1 sketch, I would need to define these variables and assign values. Can sprintf() read my variables or do I need to figure out how to pass the values to sprintf()?

In ethernet_Pachube_input_output_1_1 I think I would need something like this:

float GasMeterBTU = 0;
float CurrentAmps = 0;
float TempIn = 0;
float TempOut =0;
int GasMeterPin = 0; //digital pin 0
int CurrentPin = 0;   //analog pin 0
int TempInPin = 1;   //analog pin 1
int TempOutPin = 2   //analog pin 2

void setup()
{
  Serial.begin(57600); 
  setupEthernet(); 

  pinMode(GasMeterPin,INPUT); //gas meter pulse, define digital pin 0 as input
}

void loop()
{
  pachube_in_out();
  if digitalread(GasMeterPin) == HIGH {
        GasMeterBTU = 2409;
      } else {
        GasMeterBTU = 0;
      {

  CurrentAmps = analogRead(CurrentPin) / 100;  //I'm just making up a the scaling factor for all of these
  TempIn = analogRead(TempInPin) / 55; 
  TempOutPin = analogRead(TempOutPin) / 55:
{

Am I on the right track, or do I need to keep the analogRead variables in the springf() function?

Finally, I don't understand how the remoteSensor[] array is being used in the project. It seems to me it could replace GasMeterBTU, CurrentAmps, TempIn, TempOut variables. But in the sample sketch, I don't see where remoterSensor[3] and remoteSensore[1] are given any values.

--Scott

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Hi Scott

(by the way to get the code to render correctly in a forum post you should use "[/code]" rather than "[-/code]" to close it).

In answer to your questions:

Quote:
I'm new to the Arduino and I have several questions about this project. First, I have an Arduino Duemilanove. I don't know if this is an Arduino 14, 15 or what. This project says it was tested with Arduino 14 and has RAM problems with Arduino 15. Will my Duemilanove work with this.

Arduino 14, 15, etc. refer to versions of the IDE (i.e. software, not the hardware). Arduino is currently up to version 0017, though we haven't tried it recently ourselves, though people have had success with it. Before editing the code, try to get our demo code working, make sure it works with 17, and if not and you don't want to debug, try dropping down to 14. Your Duemilanove should work fine.

Quote:
If that's correct, then it's just reading the values of the 6 analog pins and sending this to pachube. Is that correct?
It seems to me I would need to change it to something like:

sprintf(pachube_data,"%d,%d,%d,%d,%d,%d",GasMeterBTU,CurrentAmps,TempIn,TempOut, successes + 1, failures);

That sounds about right, as long as each of those is an integer (I believe there is some demo code on the forum here if you search for using floats instead).

Quote:
Can sprintf() read my variables or do I need to figure out how to pass the values to sprintf()?

As long as the variables are global then it should work fine.

Quote:
Am I on the right track, or do I need to keep the analogRead variables in the springf() function?

Seems like the right track -- though I would probably do the variable setting *before* "pachube_in_out();".

Quote:
Finally, I don't understand how the remoteSensor[] array is being used in the project.

This code both sends your values and receives values from an existing Pachube feed. So the remoteSensor array contains values from the Pachube feed that you are requesting values from. The values are set in pachube_functions.pde.

while( result != NULL ) {
        remoteSensor[counter++] = atof(result); 
        result = strtok_r( NULL, delims, &ptr );
      } 

and are simply made available in order to control things locally.

For example

  analogWrite(3, (int)remoteSensor[3] * 10); // remoteSensor is a float
  analogWrite(5, (int)remoteSensor[1]); 

Simply adjusts your analog outputs in relation to the values of the remote Pachube feed.

Hope that helps.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

The upgrades pachube made the other day apparently broke the Arduino Ethernet Pachube Input Output code. Does anyone know how to fix it?

--Scott

Re: Arduino Ethernet and Pachube: remote sensors & web-control

I think it might be having problems here:

  if (found_status_200){
    found = strstr(buff, "_id=");
    if (found != 0){
      clean_buffer();
      found_session_id = true; 
    }
  }

I don't think it's finding" _id=" in buff. Here is what's in buff:

Server: nginx/0.6.34
Date: Mon, 18 Jan 2010 05:12:06 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
Last-Modified: Mon, 18 Jan 2010 05:12:02 GMT
X-Runtime: 21
Cache-Control: private, max-age=0, must-revalidate
Content-Length: 17
Vary: Accept-Encoding
6.8,0.0,347.9,3.5HTTP/1.1 200 OK

--Scott

Re: Arduino Ethernet and Pachube: remote sensors & web-control

just replied over here but to repeat for any subsequent visitors: that problem is easily fixed. just swap this code:

found = strstr(buff, "_id=");

with:

found = strstr(buff, "Vary:");

Re: Arduino Ethernet and Pachube: remote sensors & web-control

That worked, thanks!

Re: Arduino Ethernet and Pachube: remote sensors & web-control

I got the package working AFTER I implemented the following changes:
- entering a delay(1000) after initialization of the ethernet shield.
- entering the gateway and netmask data in the header of the program and the ethernet initialization command.

I am using my Arduino behind a Debian gateway/server/firewall.
Arduino version 0018 with standard ethernet shield.

now I am trying to figure out how I can send a floating value to Pachube (if that makes any sense).

thanks,
I got it working pretty quickly after all.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Thanks for the update.

When you say a "floating value" do you mean a float? If so, Pachube can deal with anything you send it, so just send it as a float (e.g. "3.1"). If you're trying to get sprintf to work with floats instead of integers you need to replace the "%d" with "%f" at the appropriate place.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

sprintf(pachube_data,"%f",Temperature) does not work by default in Atmel / Arduino. A "?" is printed instead. The fix is to link a floating point library additionally but since the code already occupies 50% of my codespace, i decided to do instead:

  int Temp = (int) Temperature;
  int Fraction = (Temperature - (int) Temperature) * 100;
  sprintf(pachube_data,"%d.%d",Temp, Fraction);

and that works fine now.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

In order to allow longer intervals and conform to the other variables ( millis() and last_connect ), I also changed the variable type of interval in ethernet_functions:

unsigned long interval;

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Good catch. Sounds like you've made a number of useful changes to the code, we'll try to get these included in a future update of the arduino examples (or feel free of course to post your entire code here).

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Thank you for a very good instruction and code. It is working fine, but I wonder if there is another way to restore connection once lost. I have a power monitoring system set up, and if my connection to internet is lost, I still want it to record readings. If the arduino is reset until connection is back, I will lose track of my total consumption.

Best regards,
Joachim

Re: Arduino Ethernet and Pachube: remote sensors & web-control

I have a similar problem where I use an arduino to read my gas meter and post it to pachube. I haven't coded this yet, but I'm planning on having the arduino read the most recent data from the pachube site and use this as my starting point. It's not perfect, but it's better then starting from zero. If you lose internet connection for just a short time the error will be small.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Hello,

I was wondering if anyone can help me with this:
I've been trying to get the 'Control' part working but for some reason it always disconnects. Initially it wasn't even connecting but I fixed that by declaring a gateway, as my router's IP was different.
Now this is what I see in my serial monitor:

reset ethernet
setup complete
Connecting...
GET request to retrieve
finished GET now PUT, to update
finished PUT: 930
HTTP/1.1 200 OK
Status 200 found
Server: nginx/0.6.34
Date: Sun, 04 Apr 2010 20:42:28 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
Last-Modified: Sun, 04 Apr 2010 20:36:27 GMT
X-Runtime: 5
Cache-Control: private, max-age=0, must-revalidate
Content-Length: 27
Set-Cookie: _pachube_app_session=1e503edf21bbe70e2f09d7e5805ac535; path=/; expires=Sun, 04 Apr 2010 21:42:28 GMT; HttpOnly
Vary: Accept-Encoding

d=0000000000&a=000000000000HTTP/1.1 200 OK
Status 200 found
Server: nginx/0.6.34
Date: Sun, 04 Apr 2010 20:42:29 GMT
Content-Type: text/plain; charset=utf-8
Connection: close
X-Runtime: 231
Cache-Control: private, max-age=0, must-revalidate
Content-Length: 1
Set-Cookie: _pachube_app_session=c226c31dfd50a41c06994221b0a22883; path=/; expires=Sun, 04 Apr 2010 21:42:29 GMT; HttpOnly
Vary: Accept-Encoding

 disconnecting.
=====

Any ideas? I'm using Arduino 18. I've looked at every bit of the code and I can't figure out what's wrong. I'd really appreciate some help.

Many thank,
Fahad.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

That transcript looks fine - it's connecting, making the PUT and GET statements and then disconnecting. What exactly is the problem? Are you saying that it never reconnects after that? It's only supposed to connect once every 10 seconds, unless you have changed that. If it doesn't reconnect what is the error message you receive?

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Just to clarify, this is what it's meant to do? All it does after that is just repeat the exact same thing. The above message appears in the space of 2 secs...it connects and disconnects..and resets ethernet....and then repeats the same routine.

If that is what is happening, then I don't understand why my control feed doesn't work. I've set everything according to this document. Could you possibly show a sample output of when the sketch is working normally?

Many thanks
Fahad

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Yes, it keeps connecting every 10 seconds to see whether the control values have changed.

Look at the line in your transcript that says:

d=0000000000&a=000000000000

This is the line that shows the data that it is pulling from your control feed (i.e. the one that is being read from Pachube to tell your Arduino what to do). It currently shows that all digital and all analog values are set to 0. So it's probably not doing anything because you haven't changed anything in the control feed (see '5' above).

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Thank you that really helped me understand the code further.

Now the problem is, even when I'm changing the state of digital pins on the control feed, and it's printing the right values in the array digital_state, I still don't see anything change on my digital pins. I tested my circuit with a simple blink code and the LEDs light up fine. But with the control feed data, they don't for some bizarre reason.

I looked at this bit of the code too to see if something's wrong but couldn't find anything:

 
for (int i = 0; i < 10; i++){
  
        digitalWrite( i, digital_state[i]);
    
  }

I removed the analogue bit because I'm not doing anything on the analogue pings (it doesnt work with that bit of code in either). I tried modifying the code to something like this:

 
 for (int i = 0; i < 10; i++){
      if (digital_state[i] == 1){
        digitalWrite( i, HIGH);
      }
      if (digital_state[i] == 0){
        digitalWrite(i,LOW);        
      }
  }

The main reason for that was the fact that my blink code does not work if I set the digital output to '1' rather than 'True' but this doesnt work either.

Any ideas?

Regards
Fahad

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Serial.println() is your friend! Use it to print out the values of digital_state to help you debug what's happening and where: http://www.arduino.cc/en/Serial/Println

Re: Arduino Ethernet and Pachube: remote sensors & web-control

I have just tested it with serial.println. Two observations, digital_state is equal to zero after pachube_in_out() is run. Secondly, even though the for loop should run 10 times, I get the value print about 30 times :s. This is all really really confusing and I dunno what is going wrong. I tested it for the opposite: instead of making pins high on receiving a 1, I wrote the code to make them high on receiving a 0, and it worked. So clearly, for some reason digital_state becomes all zeros again. I even tried writing all of digital_state to a new array inside the pachube_in_out function, but that doesnt work.

Any ideas? I'm really confused!

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Have you tried using Serial.println in pachube_functions.pde to debug that file too?

And have you tried the edit listed above?

Re: Arduino Ethernet and Pachube: remote sensors & web-control

It worked! And it's sweeeeet! Thanks for the support.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

I just got my Arduino up and running on Pachube! Just wanted to share a couple of comments which may be useful to others in the future:

1) Make sure that you don't use the same IP address as your computer. First, find your IP using PING, then change the last value to something between 1 and 255. For example, if your computer has the IP address: 85.180.109.78, then you can assign an IP for the Arduino as 85.180.109.79, where the last number MUST be changed.

2) You can probably just leave the MAC address in the example how it is.

3) The data which is being read in to the feed comes from the Arduino's 0-5 Analog In pins and is read out as integers to the feed. Below is an example of how sensor data from the Arduino can be changed in the pachube_functions.pde file, where the original example has been commented out for comparison:

      int val0 = (analogRead(0)*5*100)/1024; \\ converting 0-5v analog input from LM35CZ temp sensor to C
      int val1 = (analogRead(1)*5*100)/1024;

      //sprintf(pachube_data,"%d,%d,%d,%d,%d,%d,%d,%d",analogRead(0),analogRead(1),analogRead(2),analogRead(3),analogRead(4),analogRead(5), successes + 1, failures);
      sprintf(pachube_data,"%d,%d,%d,%d",val0, val1, successes + 1, failures); \\ new dataset for Pachube feed!

I was a bit concerned about the warning at the beginning of the post, but everything seemed to run fine using Arduino 0018 Alpha.

Hope that helps!

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Thanks for the update; bonus points if you refactor the code to use the DHCP library as with the wind sensor code!

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Hi guys, thanks to your code I wrote a simple sketch to share a LM35 sensor. I slightly modified your pachube_in_out() by adding an input parameter (a char array which represents the data to put to pachube) so doing you haven't to edit pachube_functions.pde (that leaves untouched, avoiding errors) and all the stuff needed to make the string to send to Pachube is wrote in loop() function:

http://telparblog.blogspot.com/2010/06/pachube-arduino-ethernet-shield-lm35.html

Please, let me know what you think about. Thanks

Frank

Re: Arduino Ethernet and Pachube:Input/Output PLEASE Help

I've almost got this working but not quite. The PUT and GET parts over the internet are working. I can see that my Pachube feed is being updated by the Arduino by looking at it. I can see the GET is working by the screen scrape of the monitor below with Serial.println 'c' enabled as below. What is not working is that the returned data from Pachube is not Serial.print.. ing. I can tell from inserting Serial.Print tests that the last part of the 'if' statement "if (found_session_id && (!found_CSV))" is not coming up with the rigth answes as I'll highlight below. Could somebody please advise how to fix this as I'm only just learning about this.

HERE IS WHAT IS SHOWING ON THE SERIAL MONITOR, The row "19.1,76,244,8.0,58.0HTTP/1.1 200 OK" is the returned data from Pachube starting with temp etc. so I know it's coming back to the Arduino OK but the loop part of the sketch that shoudl be printing this data is not happening.

MONITOR SCRAPE
reset ethernet
Ready to connect: 98041
Connecting...
GET request to retrieve
finished GET now PUT, to update
finished PUT: 98177
HTTP/1.1 200 OK
Status 200
Server: nginx/0.6.34
Date: Wed, 07 Jul 2010 18:16:36 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
Last-Modified: Wed, 07 Jul 2010 18:14:55 GMT
X-Runtime: 167
Cache-Control: private, max-age=0, must-revalidate
Content-Length: 20
Set-Cookie: _pachube_app_session=my_api_key_is_here; path=/; expires=Wed, 07 Jul 2010 18:36:36 GMT; HttpOnly
Vary: Accept-Encoding
Vary: Accept-Encoding

19.1,76,244,8.0,58.0HTTP/1.1 200 OK
Status 200
Server: nginx/0.6.34
Date: Wed, 07 Jul 2010 18:16:37 GMT
Content-Type: text/plain; charset=utf-8
Connection: close

But as you can see above, the Serial.Print of the CSV file is not happening. The follwoing bit of code is not working right. I think the first row is giving the wrong answer and thus the sketch is jumping to the row I have hopefully highlighted in red. Can somebody help me fix this please.

if (found_session_id && (!found_CSV)){
found = strstr(buff, "HTTP/1.1");
if (found != 0){
char csvLine[strlen(buff)-9];
strncpy (csvLine,buff,strlen(buff)-9);

Serial.println("This is the retrieved CSV:");
Serial.println("---");
Serial.println(csvLine);
Serial.println("---");
Serial.println("\n--- updated: ");
Serial.println(pachube_data);
Serial.println("\n--- retrieved: ");
char delims[] = ",";
char *result = NULL;
char * ptr;
result = strtok_r( buff, delims, &ptr );
int counter = 0;
while( result != NULL ) {
remoteSensor[counter++] = atof(result);
result = strtok_r( NULL, delims, &ptr );
}
for (int i = 0; i < REMOTE_FEED_DATASTREAMS; i++){
Serial.print( (int)remoteSensor[i]); // because we can't print floats
Serial.print("\t");
}

found_CSV = true;

Serial.print("\nsuccessful updates=");
Serial.println(++successes);

}
}

if (found_status_200){
found = strstr(buff, "_id=");
if (found != 0){
clean_buffer();
found_session_id = true;
}
}
}

regards

Mike

Web Remote Monitoring and Control of Real Objects using Pachube

I blogged a first working demo that use Pachube to remote monitor and control an Arduino 2009 board with Ethernet Shield at URL http://valterforesto.blogspot.com/2010/07/remote-control-of-arduino-ethernet-via.html.
The purpose of this demo is to make available via the web an example of use of Pachube for monitoring and controlling a real object connected to the Internet.

Please note that :
* the Object (Arduino 2009 and Ethernet Shield) is working and is accessible from the Internet only when I'm in my office
* the 4 Analog Outputs values are used as inputs for the 4 Analog Inputs * the 2 Digital Outputs values are used as inputs for the 2 Digital Inputs
* the typed ControlString are replayed into the StatusString

When the Object is on-line this arrangement provide immediate feedback from Control Feed set values to Status Feed reported values, when the Object is off-line you can see changes made on the Control Feed only on Pachube website and on the Google gadget in the Blog.
Comments and suggestions to improve effectiveness of this real example are welcome, contact me at 'valter.foresto@electronicbricks.it'.

You can get some code snippets for 'Arduino 2009 + Ethernet Shield connecting to Pachube' directly at link http://community.pachube.com/node/112#controller in the Pachube website under the section B "Remote Control Arduino Ethernet via web page".

You can also get my actual documentation :
Here http://www.electronicbricks.it/contenuti/pdf/ElectronicBRICKS_Pachube_Client_Object_pde-20100714a.zip the ZIP file of the sketch that I writed for the Arduino Based Object (7832 bytes on Arduino 18 IDE).
Here http://www.electronicbricks.it/contenuti/pdf/20100714.log the LOG file captured on the USB-Terminal port of the Arduino Based Object.
Use 'Display-Page Source' on your browser to see the Javascipt code for this demo.

I' m now also working on document more in depth my implemented firmware based on a Cooperative Multitasking structure and CSV Client API for Pachube and the Javascript webpage implementation for the user interaction with Control and Status Feeds on the Pachube Server side.
So, stay tuned and start to watch at the Arduino Ethernet Pachube Controller code on the above link.

Re: Arduino Ethernet and Pachube: remote sensors & web-control

Yes, I am currently running 4 LM35 CZ Temp sensors using the Duemilanove, Arduino 18 and the ethernet_Pachube_input_output_1_1.pde sketch. The feed can be found at

http://www.pachube.com/feeds/7738

I made a couple of minor modifications to pachube_functions to convert the analog readings into temp, using a delay between each reading. Hope this helps!

char pachube_data[70];

boolean found_status_200 = false;
boolean found_session_id = false;
boolean found_CSV = false;
char *found;
unsigned int successes = 0;
unsigned int failures = 0;
boolean ready_to_update = true;
boolean reading_pachube = false;

boolean request_pause = false;
boolean found_content = false;

unsigned long last_connect;

int content_length;
int ARDelay = 300;

void pachube_in_out(){

  if (millis() < last_connect) last_connect = millis();

  if (request_pause){
    if ((millis() - last_connect) > interval){
      ready_to_update = true;
      reading_pachube = false;
      request_pause = false;
      found_status_200 = false;
      found_session_id = false;
      found_CSV = false;

      //Serial.print("Ready to connect: ");
      //Serial.println(millis());
    }
  }

  if (ready_to_update){
    Serial.println("Connecting...");
    if (localClient.connect()) {

      // here we assign comma-separated values to 'data', which will update Pachube datastreams
      // we use all the analog-in values, but could of course use anything else millis(), digital
      // inputs, etc. . i also like to keep track of successful and failed connection
      // attempts, sometimes useful for determining whether there are major problems.
      
//      read in values from analog sensors, convert from analog to sensor reading, and save as val#
      int val0 = (analogRead(0)*5*100)/1024;
      delay(ARDelay); val0 = (analogRead(0)*5*100)/1024; delay(ARDelay);
      int val1 = (analogRead(2)*5*100)/1024; delay(ARDelay);
      delay(ARDelay); val1 = (analogRead(2)*5*100)/1024; delay(ARDelay);
      int val2 = (analogRead(2)*5*100)/1024; delay(ARDelay);
      delay(ARDelay); val2 = (analogRead(2)*5*100)/1024; delay(ARDelay);
      int val3 = (analogRead(3)*5*100)/1024;
      delay(ARDelay); val3 =(analogRead(3)*5*100)/1024;

      //sprintf(pachube_data,"%d,%d,%d,%d,%d,%d,%d,%d",analogRead(0),analogRead(1),analogRead(2),analogRead(3),analogRead(4),analogRead(5), successes + 1, failures);
//     using 'sprintf' to create a string csv separated inlcluding sesor data and success and failure
      sprintf(pachube_data,"%d,%d,%d,%d,%d,%d",val0, val1,val2,val3, successes + 1, failures); 
      content_length = strlen(pachube_data);

      Serial.println("GET request to retrieve");

      //localClient.print("GET /api/");
      //localClient.print(REMOTE_FEED_ID);
      //localClient.print(".csv HTTP/1.1\nHost: pachube.com\nX-PachubeApiKey: ");
      //localClient.print(PACHUBE_API_KEY);
      //localClient.print("\nUser-Agent: Arduino (Pachube In Out v1.1)");
      //localClient.println("\n");

      Serial.println("finished GET now PUT, to update");

      localClient.print("PUT /api/");
      localClient.print(SHARE_FEED_ID);
      localClient.print(".csv HTTP/1.1\nHost: pachube.com\nX-PachubeApiKey: ");
      localClient.print(PACHUBE_API_KEY);

      localClient.print("\nUser-Agent: Arduino (Pachube In Out v1.1)");
      localClient.print("\nContent-Type: text/csv\nContent-Length: ");
      localClient.print(content_length);
      localClient.print("\nConnection: close\n\n");
      localClient.print(pachube_data);



      localClient.print("\n");

      ready_to_update = false;
      reading_pachube = true;
      request_pause = false;
      interval = UPDATE_INTERVAL;

      Serial.println(pachube_data);

      Serial.print("finished PUT: ");
      // Serial.println(millis());

    } 
    else {
      Serial.print("connection failed!");
      Serial.print(++failures);
      found_status_200 = false;
      found_session_id = false;
      found_CSV = false;
      ready_to_update = false;
      reading_pachube = false;
      request_pause = true;
      last_connect = millis();
      interval = RESET_INTERVAL;
      setupEthernet();
    }
  }

  while (reading_pachube){
    while (localClient.available()) {
      checkForResponse();
    } 

    if (!localClient.connected()) {
      disconnect_pachube();
    }
  } 
}

void disconnect_pachube(){
  Serial.println("disconnecting.\n=====\n\n");
  localClient.stop();
  ready_to_update = false;
  reading_pachube = false;
  request_pause = true;
  last_connect = millis();
  found_content = false;
  resetEthernetShield();
}


void checkForResponse(){  
  char c = localClient.read();
  //Serial.print(c);
  buff[pointer] = c;
  if (pointer < 64) pointer++;
  if (c == '\n') {
    found = strstr(buff, "200 OK");
    if (found != 0){
      found_status_200 = true; 
      //Serial.println("Status 200");
    }
    buff[pointer]=0;
    found_content = true;
    clean_buffer();    
  }

  if ((found_session_id) && (!found_CSV)){
    found = strstr(buff, "HTTP/1.1");
    if (found != 0){
      char csvLine[strlen(buff)-9];
      strncpy (csvLine,buff,strlen(buff)-9);

      //Serial.println("This is the retrieved CSV:");     
      //Serial.println("---");     
      //Serial.println(csvLine);
      //Serial.println("---");   
      Serial.println("\n--- updated: ");
      Serial.println(pachube_data);
      Serial.println("\n--- retrieved: ");
      char delims[] = ",";
      char *result = NULL;
      char * ptr;
      result = strtok_r( buff, delims, &ptr );
      int counter = 0;
      while( result != NULL ) {
        remoteSensor[counter++] = atof(result); 
        result = strtok_r( NULL, delims, &ptr );
      }  
      for (int i = 0; i < REMOTE_FEED_DATASTREAMS; i++){
        Serial.print( (int)remoteSensor[i]); // because we can't print floats
        Serial.print("\t");
      }

      found_CSV = true;

      Serial.print("\nsuccessful updates=");
      Serial.println(++successes);

    }
  }

  if (found_status_200){
    found = strstr(buff, "_id=");
    if (found != 0){
      clean_buffer();
      found_session_id = true; 
    }
  }
}

Re: Arduino Ethernet and Pachube: remote sensors & web-control

NOTE: The Pachube IP address has changed from 209.40.205.190 to 173.203.98.29. Please use the new address in your code. See http://community.pachube.com/IP_address

Re: Arduino Ethernet and Pachube:Input/Output PLEASE Help

just replied over here but to repeat for any subsequent visitors: that problem is easily fixed. just swap this code:

found = strstr(buff, "_id=");
with:

found = strstr(buff, "Vary:");

right near the end of the sketch