Linux - Photon recognised - Can't proceed?

Apologies if this is in the wrong section.

I'm having trouble getting set up with an OG Photon.
I'm running Ubuntu. I was informed I had to download Chrome or Edge to get things running which I did. I made sure Chrome had permissions for USB and serial communication. It seems like the Photon is being recognized but I can't go further than step 1/4? Please look at the attached images.

Is this a website/permission/javascript problem?
Should I be holding down a button? Is my USB cable bad?

I'm at a loss. I've tried installing the CLI tool but it looks like it hasn't installed correctly or I'm using the wrong command. "particle-cli"
I've checked that the "dfu-util" package is installed and it is, however, I don't get any output from "dfu-util -l"


My first guess is that since you are using Linux, you need a udev rule for the USB port so root is not required to use it. See the instructions here for how to download and use the file.

@rickkas7

Thanks heaps. Got to the next stage now's it's tripped over again. Do I manually have to put it in to DFU mode or something?

OK, think I finally got it updated. Had to hold both setup and reset (NOT hold setup and push reset once as stated in documents)

1 Like

Is there an easy way to flip pins high or low from the browser? Last time I used this things was like 5 years ago and I seem to remember there was. Or I might be thinking of a different 3g device I had back then.

Yes, there is a web-based version of Tinker.

@rickkas7

Thanks for all the help.

Is there a Tinker app or will I have to use something like Blynk?

I'm just trying to flip a pin to drive a relay to open a garage door. Nothing crazy but I want it to be quick and easy to do on a phone. The Tinker webpage/webapp wouldn't be my first choice

On the original Photon you can create a web page with a SoftAP - not elegant, but it works.

The alternative is to create a small web page and host it somewhere - this will then call a function on the device to toggle a pin etc.

Otherwise; if your phone has a way to call the API from an app/natively (iPhone shortcuts for example) you can do that too.

@no1089

I've got a Home Assistant server.
I've also got Tasker and Google Home on my Android phone.

What do you think the easiest way to do this would be? Or am I better off binning the Photon and putting ESPHome on an ESP32 and doing it through Home Assistant?

What about Blynk?

I do like the idea of having a janky novelty app that looks like an old geocities site or myspace account. MIT App Inventor with a button that makes the aforementioned API call?

For some reason there is no integration for Home Assistant, but if you set up a custom device that's controlled via an API - it should work.
Homebridge has one - but I found it (Homebridge as a whole) very lacking and unreliable long term.

Blynk works well! It's free at the levels you'll most likely use it at - lots of folks here use it, and some even deploy products on it, so it's a solid platform. It's likely the easiest to deploy of the lot.

A basic HTML page that errors out every now and again does have it's appeal :upside_down_face:

As you noted, ESPHome is a good alternative, though I've had devices just falling offline after a couple of months - I've chalked that up to cheap modules.

@no1089

I wouldn't normally like to have home automation on anything other than self hosted, but Blynk offers a few things for this use case. A decent app that I can share this automation on very easily. Being able to trigger the Photon remotely. It's free and probably the easiest of the lot to implement.

A long time ago I flashed Blynk to an ESP8266 for an electromagnetic door lock and don't remember it being very difficult. I think I remember coding the SSID and password in and maybe a Blynk auth token.

Is the process going to be any different with the Photon? I've got VSCode and Particle Workbench ready to go.

I've found over my life that the radios tend to die a lot more often than any other components. Don't know the reason behind it or if it's just confirmation bias.

I get that - it's a tricky balance between what's not a nightmare to implement, and what exposes all of my network to the world.

Blynk integration | Integrations | Particle runs you through what's required - not too tricky to set up.

I've killed a lot of devices - I think tinkering drops a device's survivability chances a lot :sweat_smile:

@no1089

Hey mate I'm following the tutorial but am having a little trouble.

What does this section want me to do? It's a bit confusing

Particle.publish() call in the firmware:

char data[90]; 
// Note the escaped double quotes around the ""t"" for BLYNK_AUTH_TOKEN.  
snprintf(data, sizeof(data), "{\"t\":\"%s\",\"v14\":%u,\"v15\":%f,\"v16\":%u,\"v17\":%u}", BLYNK_AUTH_TOKEN, millis(), v15, led_state, led_state);
bool pub_result = Particle.publish("blynk_https_get", data, PRIVATE);

Thanks

    // Note the escaped double quotes around the ""t"" for BLYNK_AUTH_TOKEN.
    snprintf(data, sizeof(data), "{\"t\":\"%s\",\"v14\":%u,\"v15\":%f,\"v16\":%u,\"v17\":%u}", BLYNK_AUTH_TOKEN, millis(), v15, led_state, led_state);
    Serial.printlnf("Sending to Blynk: '%s' with size of %u bytes", data, strlen(data));
    bool pub_result = Particle.publish("blynk_https_get", data, PRIVATE);

When you look at the code like this it may be clearer what is meant - rather than have it Unicode-escaped.

This just means you need to wrap the key names and string values in your JSON string in double quotes ( " ).
Since C/C++ syntax uses double quotes to mark the start and end of a string literal with the same symbol, you need to tell the compiler that the embedded double qoutes are not indicating the end of the string but should be copied.
You do that by preceeding the double quote ( " ) with a backslash ( \ ) - that's called "escaping"

When you write

  char txt[] = "this \"word\" is double quoted";
  Serial.println(txt);

The output will be
this "word" is double quoted

Without the escaping you would get a compile error.

If you are unfamiliar with the meaning of snprintf() you can read this snprintf() reference and this about printf()

3 Likes

@no1089
@ScruffR

Thanks for the help guys, I've got it all working and connected however I've got one last problem. My relay is hooked up to D6 and I think the code/template I flashed is trying to use virtual pin 16 or 17. Do I need to go through the code and change something then re-flash the Photon? Or can fix it in the browser?

Thanks again

Oh and before I forget. I intend to change wireless access points in the near future, Is there an easy way to let the Photon know what the new SSID and password is? I'm not sure but I guess particle will have facility somewhere on their system to change wifi credentials over the air?

Thanks heaps :slight_smile:

It would be best to change your code to actually use the pin designator (aka name) rather than the anonymous pin number.
If you are really using an original Photon than pins 16 and 17 would be A6/DAC and A7/WKP respectively.

With an original Photon there are multiple ways to add WiFi credentials but none of them is OTA but via USB (e.g. here Device Restore USB | Tools | Particle)

However, you can use WiFi.setCredentials() to add new WiFi credentials - e.g. in a dedicated Particle.function() to do it OTA.

@ScruffR

When I flashed an esp8266 years ago with the blynk firmware/server and installed the android app on my phone, it was super simple. make a button in the GUI and assign it to a physical pin number for the MCU. It just worked.

Right now I'm using an original photon and particle relay board. I would like to be able to use the Blynk app to flip D3, D4, D5 and D6. That's about it. Nothing crazy. I don't know anything about virtual pins or anonymous pin numbers.

Is the code I've flashed from the template completely inappropriate for this use?

#include "Particle.h"

// *** MAIN SETTINGS ***
// Replace this block with correct template settings.
// You can find it for every template here:
//
//   https://blynk.cloud/dashboard/templates

#define BLYNK_TEMPLATE_ID "TMPL6D6Yf97Bw"
#define BLYNK_TEMPLATE_NAME "Connect a Particle device"
#define BLYNK_AUTH_TOKEN "xxx"

const char *firmware_version = "0.0.0";

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

#include <math.h> // This library is only for function simulating a sensor

double v15 = 3.14159;
uint32_t simSensor_timer_last = 0; // This is a variable for a function that simulates a sensor
uint8_t led_state = LOW;
bool particle_fn_called = TRUE; // causes the device to publish data immediately after started/boot and connected to the Particle cloud.

// Register the Particle cloud function
int blynkLED(String on_or_off);

inline
float approx_cos(float x)
{
  constexpr float tp = 1.0/(2.0*M_PI);
  x *= tp;
  x -= 0.25f + floor(x + 0.25f);
  x *= 16.0f * (abs(x) - 0.5f);
  x += 0.225f * x * (abs(x) - 1.0f);
  return x;
}

void simSensor()    //This function simulates a sensor
{ 
  long sim = random(millis());
  if (millis() - simSensor_timer_last >= 20000) {
    simSensor_timer_last = millis();
    float deltaSensor = approx_cos(float(sim) / 1000) / 100;
       if (v15 <= 0 || v15 >= 3.3)
    {
      v15 = v15 - deltaSensor;
    }
    else
    {
      v15 = v15 + deltaSensor;
     }
  }
} // simSensor

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

bool deviceHasLedOnD7()
{
  // Returns TRUE if the device has a built-in LED on D7:
  //  Boron, Argon, Photon 2, Photon, Electron, Core
  // 8: P1
  switch (PLATFORM_ID)
  {
  case PLATFORM_BORON:
  case PLATFORM_ARGON:
  case 0:  // Core
  case 6:  // Photon  (PLATFORM_PHOTON_PRODUCTION)
  case 10: // Electron  (PLATFORM_ELECTRON_PRODUCTION)
    return TRUE;
  default:
    return FALSE;
  }
} // deviceHasLedOnD7()

/////////////////////////////////////////////////////////////////////////
// Timer

const uint32_t TIMER_INTERVAL_MS = 300000L;
uint32_t timer_last = 0;

void pubToParticleBlynk()
{
  if (Particle.connected())
  {
    
    char data[128];

    snprintf(data, sizeof(data),
                 R"json({"t":"%s","v14":"%u","v15":"%f","v16":"%u","v17":"%u"})json",
                 BLYNK_AUTH_TOKEN, millis(), v15, led_state, led_state);
    Serial.printlnf("Sending to Blynk: '%s' with size of %u bytes", data, strlen(data));
    bool pub_result = Particle.publish("blynk_https_get", data, PRIVATE);
    if (pub_result)
    {
      timer_last = millis();
    }
    else
    {
      Serial.println("ERROR: Particle.publish()");
    }
  }
} // pubToParticleBlynk()

void pubTimer()
{
  // A timer for publishing data to Particle Cloud, and then continuing to Blynk.
  if (timer_last > millis())
    timer_last = millis();
  if ((millis() - timer_last) > TIMER_INTERVAL_MS && Particle.connected())
  {
    pubToParticleBlynk();
    timer_last = millis();
  }
} // pubTimer()

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

void setup()
{
  

  if (deviceHasLedOnD7() == TRUE)
  {
    pinMode(D7, OUTPUT);
    digitalWrite(D7, LOW);
  }

  Serial.begin(9600);
  waitFor(Serial.isConnected, 5000);
  delay(1000);
  Serial.printlnf("Device OS v%s", System.version().c_str());
  Serial.printlnf("Free RAM %lu bytes", System.freeMemory());
  Serial.printlnf("Firmware version v%s", firmware_version);

  // register the Particle cloud function (funcKey, funcName)
  Particle.function("blynk_led", blynkLED);

  Serial.println("Setup complete");

} // setup()

void loop()
{
  simSensor(); // This is function simulates a sensor
  pubTimer();
  

  if (particle_fn_called == TRUE)
  {
    particle_fn_called = FALSE;
    // Publish data to Particle cloud..
    pubToParticleBlynk();
  }

  if (deviceHasLedOnD7() == TRUE)
  {
    digitalWrite(D7, led_state);
  }

} // loop()

int blynkLED(String on_off)
{
  // Custom Particle cloud function that changes the state of the built-in LED
  // on D7 in response to an instruction from Blynk calling this
  // custom cloud function.
  // Returns the value 1 if the LED has been turned on, and 0 if turned off,
  // -1 if an unexpected on_off value is received.
  // Cloud functions must return int and take one String argument
  // curl https://api.particle.io/v1/devices/{your 25 char device id}/blynk_led
  // -d access_token={your 40 char access token}
  // -d "args=on/off"

  if (on_off == "on" || on_off == "1")
  {
    particle_fn_called = TRUE;
    led_state = HIGH;
    return 1;
  }
  else if (on_off == "off" || on_off == "0")
  {
    particle_fn_called = TRUE;
    led_state = LOW;
    return 0;
  }
  else
  {
    Serial.print("Unexpected on_off value of: '");
    Serial.print(on_off);
    Serial.println("'");
  }
  return -1;

} // blynkLED()

The "anonymous" pin number for D6 would be 6 - on Photon the pins D0..D7 are numbered 00..07 respectively, while all Ax pins are numbered 10..17.

Since I don't see any reference to any other pin than the D7 LED in your code, and have stopped using Blynk ages ago, I couldn't say where the link between Blynk's virtual pins and the actual HW pins should be created.