Combining string and int in to Twitter message

Hi everyone,

I'm new to Arduino and as a really basic project I thought I'd try and produce something simple but fun. The idea is that you turn a pot which light up LEDs between 1 and 5 then you hit a button and it sends your rating to Twitter.

I'm stumbling on combining a random string with the rating, I'm not sure what the best way to do it is or how to mash up a string with an integer to create a pure string to send to Twitter.

Here's what I have so far.

#include <SPI.h> // needed in Arduino 0019 or later
#include <Ethernet.h>
#include <Twitter.h>

// Ethernet Shield Settings
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

const int submitButtonPin = 9;     // the number of the pushbutton pin
int ledPin[] = {2,3,4,5,6};
int ratingDial = A0;
int rating;
int i;
int ratingIn;
int submitButton = 0;         // variable for reading the pushbutton status

// Your Token to Tweet (get it from http://arduino-tweet.appspot.com/)
Twitter twitter("my token goes in here");

// Message to post
char msg[] = {};

void setup() {

  delay(1000);
  Ethernet.begin(mac);
  // or you can use DHCP for autoomatic IP address configuration.
  // Ethernet.begin(mac);
  Serial.begin(9600);

  // initialize the LED pin as an output:
  for (i = 1; i < 5; i++) {
  pinMode(ledPin[i], OUTPUT);      
    }
  pinMode(submitButtonPin, INPUT);     
  
}

void loop(){
  submitButton = digitalRead(submitButtonPin);
  ratingIn = analogRead(ratingDial);
  rating = map(ratingIn, 0, 1024, 1, 6);
  LEDrating();
  
    if (submitButton == LOW) { 
  messageMaker(); // Create a random message with the rating in.    
    Serial.println(msg); // print the rating
   submitted();   
  } 
}

void LEDrating() {
    for (i = 0; i < 5; i++){
     digitalWrite(ledPin[i], LOW);
  }
  for (i = 0; i < rating; i++){
    digitalWrite(ledPin[i], HIGH);
  }
}

void submitted(){

  //Send the rating to Twitter for the world to see.
  Serial.println("connecting ...");
  if (twitter.post(msg[])) {
    // Specify &Serial to output received response to Serial.
    // If no output is required, you can just omit the argument, e.g.
    // int status = twitter.wait();
    int status = twitter.wait(&Serial);
    if (status == 200) {
      Serial.println("OK.");
    } else {
      Serial.print("failed : code ");
      Serial.println(status);
    }
  } else {
    Serial.println("connection failed.");
  }
  // End of Twitter
  
  
      for (i = 0; i < 5; i++){
      digitalWrite(ledPin[i], LOW);
      delay(50);      
  }
  delay(100);
  for (i = 0; i < 5; i++){
      digitalWrite(ledPin[i], HIGH);
      delay(50);
    
  }
  delay(100);
}

void messageMaker() {
 String convertRating = String(rating);
 msg = "One of our customers just rated us " && convertRating;

}
char msg[] = {};

The compiler determines the size of the array from the number of initializers present. How big do you think this array is?

void setup() {

  delay(1000);

When the Arduino is powered up, wait a full second before doing anything. Why?

void messageMaker() {
 String convertRating = String(rating);
 msg = "One of our customers just rated us " && convertRating;

}

The rating value is converted to a String. That String is copied to another String. The msg array is then what? You can not assign a String or string literal to a no-space array this way.

You need to define a fixed size for the msg array. You need to get rid of all String objects. They just waste space.

char msg[80];

void messageMaker()
{
   sprintf(msg, "One of our customers just rated us %i", convertRating);
}

Thanks so much, it's now working. For anyone else having similar issues or trying to do something similar, code below.

#include <SPI.h> // needed in Arduino 0019 or later
#include <Ethernet.h>
#include <Twitter.h>

// Ethernet Shield Settings
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC address of the ethernet shield

const int submitButtonPin = 9;     // The number of the pushbutton pin
int ledPin[] = {2,3,4,5,6};        // The LEDs set up as an array to cut down on code
int ratingDial = A0;              // Setting up a variable for the Potentiometer
int ratingIn;                     // Variable for getting the raw reading of the potentiometer
int rating;                      // A variable to store the rating in
int i;                          // Setting up the variable i so it can be used for array loops
int submitButton = 0;         // variable for reading the pushbutton status
char msg[140];               // Setting up the variable to hold the final Twitter message to be sent

// Your Token to Tweet (get it from http://arduino-tweet.appspot.com/)
Twitter twitter("Your API Twitter Token here");

void setup() {

  Ethernet.begin(mac);
  Serial.begin(9600);

  // initialize the LED pins as an output:
  for (i = 1; i < 5; i++) {
  pinMode(ledPin[i], OUTPUT);      
    }
  pinMode(submitButtonPin, INPUT);     
}

void loop(){
  submitButton = digitalRead(submitButtonPin); // Get the values from the push buttons
     
  ratingIn = analogRead(ratingDial);          // Read the raw value from the potentiometer
  rating = map(ratingIn, 0, 1024, 1, 6);    // remap the raw value to the range of 1 to 5 
  LEDrating();                              // Go to the LEDrating function
  
  
  
    if (submitButton == LOW) { 
  messageMaker(); // Create a random message with the rating in.    
    Serial.println(msg); // print the rating to the serial out for debugging purposes
   submitted();         // Run the submitted function
  } 
}

// This loops through the LEDs turning them all off and then looping through again and turning the the correct amount on

void LEDrating() {
    for (i = 0; i < 5; i++){
     digitalWrite(ledPin[i], LOW);
  }
  for (i = 0; i < rating; i++){
    digitalWrite(ledPin[i], HIGH);
  }
}

// Connect and send the message to twitter 
void submitted(){

  //Send the rating to Twitter for the world to see.
  Serial.println("connecting ...");
  if (twitter.post(msg)) {
    int status = twitter.wait(&Serial);
    if (status == 200) {
      Serial.println("OK.");
    } else {
      Serial.print("failed : code ");
      Serial.println(status);
    }
  } else {
    Serial.println("connection failed.");
  }
  // End of Twitter
  
 // Celebration code, makes the LEDs flash on and off to tell the user the rating has been sent.
      for (i = 0; i < 5; i++){
      digitalWrite(ledPin[i], LOW);
      delay(50);      
  }
  delay(100);
  for (i = 0; i < 5; i++){
      digitalWrite(ledPin[i], HIGH);
      delay(50);
    
  }
  delay(100);
}

// This code constructs the message to be sent using the rating value and some strings of text (eventually).
void messageMaker()
{
   sprintf(msg, "One of our customers just rated us %i stars!", rating);
}

One thing to keep in mind is that the twit system will start rejecting posts if the same (5) messages appear over and over. You might want to revise the message to include a random number or the time/date (or even how long the Arduino has been running, using millis()), so that the messages stand a better chance of being unique.

Or, use your own server to get around the "problem".

I plan to have random messages with the rating in but I haven't got around to that yet, It's next on my list and should get around the issue hopefully.

Hi there,

did you manage to work out how to include a random message within the msg? I'm trying to do something similar but haven't managed to work it out yet

Thanks

did you manage to work out how to include a random message within the msg? I'm trying to do something similar but haven't managed to work it out yet

Did you notice the theme of this forum? Programming almost always involves code. Where's yours?

Adding a string and an int is trivial. Adding a string and the time is trivial. Adding a string and a random number, or a string based on using the random number as an index is trivial. Well, trivial after you've done it a few hundred times.

Show what you have attempted, and the proof that it does not do what you want, and we'll help you fix it.

Hi there,

Sorry, that was more a question aimed at the OP, but I'd really appreciate some input.

What I have already is quoted below, but what I'd like to do now is replace the bit that reads "" with a randomly picked message from a list of, say, 10 messages I define elsewhere in the code.

Any pointers would be really appreciated.

This is working (just prints a single message with an incrementing number):

#include <SPI.h> // needed in Arduino 0019 or later
#include <Ethernet.h>
#include <Twitter.h>

// constants won’t change. They’re used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin
// variables will change:
// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 
  192, 168, 2, 250 };

// Your Token to Tweet
Twitter twitter("YOUR TOKEN HERE");

// Message to post
char msg[64];

void setup()
{
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);    

  delay(1000);
  //Ethernet.begin(mac, ip);
  // or you can use DHCP for autoomatic IP address configuration.
  Ethernet.begin(mac);
  Serial.begin(9600);
  Serial.println("I am connecting ...");
}

void loop(){

  buttonState = digitalRead(buttonPin);

  // if the state has changed, increment the counter
  if (buttonState == HIGH) {
    // compare the buttonState to its previous state
    if (buttonState != lastButtonState) {

      digitalWrite(ledPin, HIGH); 

      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
      Serial.println("button pressed");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
      
      snprintf (msg, 64, "<insert string from list here>: %d", buttonPushCounter);

      if (twitter.post(msg)) {
        int status = twitter.wait();
        if (status == 200) {
          Serial.println("Tweeted!");
        } 
        else {
          Serial.print("failed : code ");
          Serial.println(status);
        } 
      }
      else {
        Serial.println("connection failed.");
      }

    }
    else {
      // turn LED off:
      digitalWrite(ledPin, LOW);
    }
  }
  // save the current state as the last state, 
  //for next time through the loop
  lastButtonState = buttonState;
}

One thing I've tried is this (but it's not working):

#include <SPI.h> // needed in Arduino 0019 or later
#include <Ethernet.h>
#include <Twitter.h>

// constants won’t change. They’re used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin
// variables will change:
// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 2, 250 };

// Your Token to Tweet
Twitter twitter("YOUR TOKEN HERE");

// Message to post
char msg[64];

void setup()
{
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);    

  delay(1000);
  //Ethernet.begin(mac, ip);
  // or you can use DHCP for autoomatic IP address configuration.
  Ethernet.begin(mac);
  Serial.begin(9600);
  Serial.println("I am connecting ...");
  
  
#define NUMMSG 48

prog_char msg0[] PROGMEM = "message A";
prog_char msg1[] PROGMEM = "a different message B";
prog_char msg2[] PROGMEM = "another message C";
prog_char msg3[] PROGMEM = "Something else D";
prog_char msg4[] PROGMEM = "msg E";
prog_char msg5[] PROGMEM = "Another msg F";
prog_char msg6[] PROGMEM = "message G";

PROGMEM const char *messages[] = {
  msg0, msg1, msg2, msg3, msg4, msg5, msg6
};
  
  
}

void loop(){

  buttonState = digitalRead(buttonPin);

  // if the state has changed, increment the counter
  if (buttonState == HIGH) {
    // compare the buttonState to its previous state
    if (buttonState != lastButtonState) {

      digitalWrite(ledPin, HIGH); 

      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
      Serial.println("button pressed");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
      
      // writes the msg to tweet with %d number defined by butoonPushCounter
      snprintf (msg, 64, "random(NUMMSG), %d", buttonPushCounter);

      if (twitter.post(msg)) {
        int status = twitter.wait();
        if (status == 200) {
          Serial.println("Tweeted!");
        } 
        else {
          Serial.print("failed : code ");
          Serial.println(status);
        } 
      }
      else {
        Serial.println("connection failed.");
      }

    }
    else {
      // turn LED off:
      digitalWrite(ledPin, LOW);
    }
  }
  // save the current state as the last state, 
  //for next time through the loop
  lastButtonState = buttonState;
}
      // writes the msg to tweet with %d number defined by butoonPushCounter
      snprintf (msg, 64, "random(NUMMSG), %d", buttonPushCounter);

"random(NUMMSG)", despite looking like a function call, is not calling the random function. Inside the quotes, it is a literal string. The only variable portion of the message is the value in buttonPushCounter.

If you want msg to contain one of the random messages you stored in progmem, you need to create a random number, by calling random(), then copy the message at that index location from PROGMEM to SRAM, then post it.

Thanks for the tip. Sorry I'm really new to this type of coding.

Would that all happen within:

 snprintf ();

?

I have tried doing that by using the line:

   snprintf (msg, 64, "%r, %d", random(NUMMSG), buttonPushCounter);

but now all I get is a "failed : code 403" message in my serial monitor.

Thanks

Would that all happen within:

No, it would not.

%r

???

Try something like this:

   int msgNum = random(NUMMSG);
   char msgBfr[60]; // Sized to hold string to retrieve
   strcpy_P(msgBfr, (char*)pgm_read_word(&(messages[msgNum])));
   snprintf (msg, 64, "%s, %d", msgBfr, buttonPushCounter);

Thanks very much, however, I'm getting this error:

tweet_when_a_button_is_pressed3.cpp: In function 'void loop()':
tweet_when_a_button_is_pressed3:75: error: 'messages' was not declared in this scope

Why would that happen?

Thanks very much, however, I'm getting this error:

tweet_when_a_button_is_pressed3.cpp: In function 'void loop()':
tweet_when_a_button_is_pressed3:75: error: 'messages' was not declared in this scope

Why would that happen?

Well, I'm not the one that declared the messages array inside the setup() function.

ok, rectified that mistake.

Program seems to upload ok now and run, but I'm getting a 'failed : code 403' message in my serial monitor now. Would this be because I've been fiddling with twitter too much and gone over my rate limit?

Or perhaps it's to do with my code?

#include <SPI.h> // needed in Arduino 0019 or later
#include <Ethernet.h>
#include <Twitter.h>

// constants won’t change. They’re used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin
// variables will change:
// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 2, 250 };

// Your Token to Tweet
Twitter twitter("Your Token here");

// Message to post
char msg[64];

#define NUMMSG

prog_char msg0[] PROGMEM = "message A";
prog_char msg1[] PROGMEM = "message B";
prog_char msg2[] PROGMEM = "message C";
prog_char msg3[] PROGMEM = "message D";
prog_char msg4[] PROGMEM = "message E";
prog_char msg5[] PROGMEM = "message F";
prog_char msg6[] PROGMEM = "message G";

PROGMEM const char *messages[] = {
  msg0, msg1, msg2, msg3, msg4, msg5, msg6
};


void setup()
{
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);    

  delay(1000);
  //Ethernet.begin(mac, ip);
  // or you can use DHCP for autoomatic IP address configuration.
  Ethernet.begin(mac);
  Serial.begin(9600);
  Serial.println("I am connecting ..."); 
}

void loop(){

  buttonState = digitalRead(buttonPin);

  // if the state has changed, increment the counter
  if (buttonState == HIGH) {
    // compare the buttonState to its previous state
    if (buttonState != lastButtonState) {

      digitalWrite(ledPin, HIGH); 

      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
      Serial.println("button pressed");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
      
//this should tweet a random message from the list as well as the number of times the button has been pressed
     int msgNum = random(NUMMSG);
     char msgBfr[64]; // Sized to hold string to retrieve
     strcpy_P(msgBfr, (char*)pgm_read_word(&(messages[msgNum])));
     snprintf (msg, 64, "%s, %d", msgBfr, buttonPushCounter);

      if (twitter.post(msg)) {
        int status = twitter.wait();
        if (status == 200) {
          Serial.println("Tweeted!");
        } 
        else {
          Serial.print("failed : code ");
          Serial.println(status);
        } 
      }
      else {
        Serial.println("connection failed.");
      }

    }
    else {
      // turn LED off:
      digitalWrite(ledPin, LOW);
    }
  }
  // save the current state as the last state, 
  //for next time through the loop
  lastButtonState = buttonState;
}

Would this be because I've been fiddling with twitter too much and gone over my rate limit?

Beats me. I use my own server for posting to. I've never been a fan of twitter.

However:
http://www.w3.org/Protocols/HTTP/HTRESP.html

Forbidden 403

The request is for something forbidden. Authorization will not help.

I'd check that twitter token to make sure that it is right.

yep, the token's ok. When I go back to using my older code that only includes the single message and counter:

      snprintf (msg, 64, "my message %d", buttonPushCounter);

instead of:

     int msgNum = random(NUMMSG);
     char msgBfr[64]; // Sized to hold string to retrieve
     strcpy_P(msgBfr, (char*)pgm_read_word(&(messages[msgNum])));
     snprintf (msg, 64, "%s, %d", msgBfr, buttonPushCounter);

I don't get the error message... Ah well, I'll try to work this out.

Thanks again for you help.

Ah well...

Ah well, I'll try to work this out.

User Serial.print() and Serial.println() to print the random number, the message retrieved, the message to be sent, etc.

Nothing is obviously wrong, but I like to know (at least once) what is really going on.