element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Save The Bees Design Challenge
  • Challenges & Projects
  • Design Challenges
  • Save The Bees Design Challenge
  • More
  • Cancel
Save The Bees Design Challenge
Blog Name That Bee
  • Blog
  • Forum
  • Documents
  • Leaderboard
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Save The Bees Design Challenge to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: dougw
  • Date Created: 6 Mar 2023 2:11 AM Date Created
  • Views 26957 views
  • Likes 6 likes
  • Comments 5 comments
  • save the bees
  • huskylens
  • savethebeesch
  • dougw
  • speech synthesis
  • mkr wan 1310
Related
Recommended

Name That Bee

dougw
dougw
6 Mar 2023

Intro

The kit arrived, so I can start to learn what Nicla Vision is, but this blog will focus on integrating a couple of subsystems to work out how they interface to each other.
I want the HuskyLens to put the correct name to classified objects. This requires some programming.
This episode also covers the firmware needed to query HuskyLens about what it has recognized.
I worked on getting a LoRa link working as well but it looks like one of the LoRa radios is not working, but at least there is a start on the firmware.
The new speech synthesis modules arrived so the cast now have their own voices.
I will use the Arduino MKR 1300 to control the HuskyLens and the new speech synthesis module. This will allow the system to interact with the cast of characters by recognizing each one and using that information to trigger interactive speech.
A stretch goal for this blog is to get wireless interaction started - working out LoRa communications.

The Build For This Episode:
These intermediate builds are needed because the PCBs have not arrived and I need some hardware to test firmware. I had to clean them up from the first breadboard lashup.

The Crystal System
The Crystal System is the base station back at the ranch. It has a MKR WAN 1300, an LCD and a single voice speech synthesis module.

image

The Lora System
The Lora System is the remote system out in the field - it recognizes bees and insects and reports back to the Crystal System.
It consists of a Huskylens, a MKR WAN 1310 and a multi-voice speech synthesis module.

image

Adding Real Names To Classified Objects
To add names to recognized opjects requires programming from an external MCU. For this I used an Arduino UNO because it is not clear what voltages Husky uses when communicating. It can run off 3.3 or 5V but when running off 5V, will it hurt connected devices that run off 3.3V? I didn't take any chances and used a 5V UNO. Note the custom 3D printed GoPro mount for the Huskylens. In this image the Huskylens has identified the ladybug and correctly labelled the image:

image

Here is the program used to assign names to the recognized objects:

/***************************************************
 HUSKYLENS utility to name classified objects
 The program runs on an Arduino UNO
 Doug Wong 2023
**************************************************/

#include "HUSKYLENS.h"
#include "SoftwareSerial.h"

HUSKYLENS huskylens;
SoftwareSerial mySerial(10, 11); // RX, TX
//HUSKYLENS green line >> Pin 10; blue line >> Pin 11

  void setNewName (String newname, uint8_t ID){
    while (!huskylens.setCustomName(newname, ID))
    {
      Serial.println("Custom name failed");
    }
   }

void setup()
{
    Serial.begin(9600);
    mySerial.begin(9600);
    while (!huskylens.begin(mySerial))
    {
        Serial.println("Begin failed!");
        Serial.println("1.Please recheck the \"Protocol Type\" in HUSKYLENS (General Settings>>Protocol Type>>Serial 9600)");
        Serial.println("2.Please recheck the connection.");
        delay(100);
    }
    delay(100);
    
  // change names

    setNewName ("BeeOne", 1);
    setNewName ("BeeTwo", 2);
    setNewName ("Spiderman", 3);
    setNewName ("Cindy Cicada", 4);
    setNewName ("Grasshopper", 5);
    setNewName ("Ladybug", 6);
}

void loop()
{
}

Querying Husky to Know What Obejct Was Recognized
Here is the firmware used to sort out how to query the Huskylens and find out what it recognized:

/***************************************************
 HUSKYLENS Oject Classification Monitor
 Program to test how to query the Huskylens to get IDs of recognized objects
  Doug Wong 2023
 ****************************************************/

#include "HUSKYLENS.h"
#include "SoftwareSerial.h"

HUSKYLENS huskylens;
//HUSKYLENS green line >> SDA; blue line >> SCL
int ID0 = 0; //not learned results. Grey result on HUSKYLENS screen
int ID1 = 1; //first learned result - BeeOne
int ID2 = 2; //second learned result - TwoBee
int ID3 = 3; //third learned result - Spiderman
int ID4 = 4; //fourth learned result - Cindy
int ID5 = 5; //fifth learned result - Grasshopper
int ID6 = 6; //sixth learned result - Ladybug

SoftwareSerial mySerial(10, 11); // RX, TX

void printResult(HUSKYLENSResult result);

void setup() {
    Serial.begin(9600);
    mySerial.begin(9600);
    while (!huskylens.begin(mySerial))
    {
        Serial.println(F("Begin failed!"));
        Serial.println(F("1.Please recheck the \"Protocol Type\" in HUSKYLENS (General Settings>>Protocol Type>>I2C)"));
        Serial.println(F("2.Please recheck the connection."));
        delay(100);
    }
    
       huskylens.writeAlgorithm(ALGORITHM_OBJECT_RECOGNITION);
}

void loop() {
    if (huskylens.request())                    //request all blocks and arrows from HUSKYLENS
    if (huskylens.requestBlocks(ID1))        //request blocks tangged ID == ID1 from HUSKYLENS
      {
        for (int i = 0; i < huskylens.count(ID1); i++)
        {
            HUSKYLENSResult result = huskylens.get(ID1, i);
            printResult(result);
        }
      }
    if (huskylens.requestBlocks(ID2))        //request blocks tangged ID == ID2 from HUSKYLENS
      {
        for (int i = 0; i < huskylens.count(ID2); i++)
        {
            HUSKYLENSResult result = huskylens.get(ID2, i);
            printResult(result);
        }
      }
    if (huskylens.requestBlocks(ID3))        //request blocks tangged ID == ID3 from HUSKYLENS
      {
        for (int i = 0; i < huskylens.count(ID3); i++)
        {
            HUSKYLENSResult result = huskylens.get(ID3, i);
            printResult(result);
        }
      }
    if (huskylens.requestBlocks(ID4))        //request blocks tangged ID == ID4 from HUSKYLENS
      {
        for (int i = 0; i < huskylens.count(ID4); i++)
        {
            HUSKYLENSResult result = huskylens.get(ID4, i);
            printResult(result);
        }
      }
    if (huskylens.requestBlocks(ID5))        //request blocks tangged ID == ID5 from HUSKYLENS
      {
        for (int i = 0; i < huskylens.count(ID5); i++)
        {
            HUSKYLENSResult result = huskylens.get(ID5, i);
            printResult(result);
        }
      }
    if (huskylens.requestBlocks(ID6))        //request blocks tangged ID == ID6 from HUSKYLENS
    {
        for (int i = 0; i < huskylens.count(ID6); i++)
        {
            HUSKYLENSResult result = huskylens.get(ID6, i);
            printResult(result);
        }
    }
    else
    {
        Serial.println("Fail to request objects from Huskylens!");
    }
}

void printResult(HUSKYLENSResult result){
    if (result.command == COMMAND_RETURN_BLOCK){//result is a block
        Serial.println(String()+F(",ID=")+result.ID);
    }
    else{//result is unknown.
        Serial.println("Object unknown!");
    }
    delay (200);
}

To demonstrate the recognition / naming ability of Husky a bracket was designed and printed to mount the Huskylens in front of a video camera. Here is what the HuskyLens bracket looks like - that keeps the HuskyLens correctly positioned in front of the video camera:

image

Here is a short video showing what that camera sees when looking at the Huskylens and showing what some of the voices sound like:

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Here is the firmware running all the different voices:

/*
  Speech Syth Controller + MKR 1310
  Uses a XFS5152 text-to-speech module to talk
  by Doug Wong   2023
*/
#include <SPI.h>
#include <LoRa.h>
#define PIN_SCE   6       //chip select pin for LCD
#define PIN_RESET 10      //reset pin for LCD
#define PIN_DC    7       //data / command select pin for LCD
#define PIN_SDIN  8       //serial data input pin for LCD (MOSI)
#define PIN_SCLK  9       //SPI clock pin for LCD
#define LCD_C     LOW     //this value select command mode on LCD DC
#define LCD_D     HIGH    //this value select data mode on LCD DC
#define LCD_X     84      //number of pixels on an LCD line
#define LCD_Y     48      //number of vertical pixels on LCD

const unsigned long SEND_INT = 5000;         // Sends a msg on this interval (milliSec)
char rsi;                        // receive signal strength
int rssi;                        // recieve signal strength
int packetSize;                  // LoRa recieved packet size
char LoRaIn;                     // character received via LoRa
char LoRaInStr[2];
char LoRaChar;
String rsis;
char rsia[4];

char LoRaString[1];

byte synback;

bool news;            //new sighting flag
byte critr;           //critter number
char crits[2];        //critter number as a charchar LoRaChar;
String critss;

void speak(char* msg) {
  Serial1.write(0xFD);              //Start Byte
  Serial1.write((byte)0x0);         //length of message string - high byte
  Serial1.write(2 + strlen(msg));   //length of message - low byte
  Serial1.write(0x01);              //command 01 = speak message
  Serial1.write((byte)0x0);         //text encoding format 0-3
  Serial1.write(msg);               //message to speak
}

void waitForSpeech(unsigned long timeout = 60000) {
  unsigned long start = millis();
  bool done = false;
  while ( ! done && (millis() - start) < timeout ) {
    while ( Serial1.available() ) {
      if ( Serial1.read() == 0x4F ) {
        done = true;
        break;
      }
    }
  }
}

// Speech Parameters
// f0 - stress each syllable        n0 - auto digital
// f1 - normal synthesis            n1 - digital number
// g0 - auto determine language     n2 - digital value
// g1 - numeral, units, symbols     o0 - "zero"
// g2 - english synthesis           o1 - European
// h0 - auto word diction           pn - n = pause duration in ms
// h1 - letter by letter diction    r0 - auto surname
// h2 - word by word diction        r1 - surname rules
// i0 - no Pinyin                   sn - n = speech speed 0-10
// i1 - Pinyin                      tn - n = tone 0-10
// m3 - asian female voice          vn - n = volume 0-10
// m51- male voice                  x0 - no tone
// m52 - generic male               x1 - use tone
// m53 - generic female             y0 - 1 = unitary
// m54 - cartoon                    y1 - 1 = one
// m55 - girl                       z0 - * # = symbols
// =n - inflection n = 1-5          d - restore default

//Chartacter Voices
// Oh Bee One     [h0][f1][m51][t3][s5]
// Two Bee        [f1][m53][t8][s6]
// Lora           [f1][m53][t5][s5]
// Husky          [f1][m51][t4][s5]
// Spiderman      [f1][m51][t6][s4]
// Cindy Cicada   [f1][m3][t7][s6]
// Grasshopper    [f1][m20][t2][s7]
// Ladybug        [f1][m55][t5][s6]
// Crystal        [f1][m53][t7][s5]
// Ardu           [f1][m51][t5][s5]


// pixel map of character set for LCD
static const byte ASCII[][5] =
{
  {0x00, 0x00, 0x00, 0x00, 0x00} // 20
  , {0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
  , {0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
  , {0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
  , {0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
  , {0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
  , {0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
  , {0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
  , {0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
  , {0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
  , {0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
  , {0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
  , {0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
  , {0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
  , {0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
  , {0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
  , {0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
  , {0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
  , {0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
  , {0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
  , {0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
  , {0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
  , {0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
  , {0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
  , {0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
  , {0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
  , {0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
  , {0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
  , {0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
  , {0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
  , {0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
  , {0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
  , {0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
  , {0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
  , {0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
  , {0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
  , {0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
  , {0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
  , {0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
  , {0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
  , {0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
  , {0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
  , {0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
  , {0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
  , {0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
  , {0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
  , {0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
  , {0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
  , {0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
  , {0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
  , {0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
  , {0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
  , {0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
  , {0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
  , {0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
  , {0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
  , {0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
  , {0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
  , {0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
  , {0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
  , {0x02, 0x04, 0x08, 0x10, 0x20} // 5c ¥
  , {0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
  , {0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
  , {0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
  , {0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
  , {0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
  , {0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
  , {0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
  , {0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
  , {0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
  , {0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
  , {0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
  , {0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
  , {0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
  , {0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j
  , {0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
  , {0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
  , {0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
  , {0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
  , {0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
  , {0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
  , {0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
  , {0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
  , {0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
  , {0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
  , {0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
  , {0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
  , {0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
  , {0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
  , {0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
  , {0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
  , {0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
  , {0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
  , {0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
  , {0x10, 0x08, 0x08, 0x10, 0x08} // 7e ←
  , {0x78, 0x46, 0x41, 0x46, 0x78} // 7f →
};

void LcdCharacter(char character)                       // display a character on the LCD
{
  LcdWrite(LCD_D, 0x00);                                // display a blank space before character
  for (int index = 0; index < 5; index++)               // font uses 5 x 7 pixels
  {
    LcdWrite(LCD_D, ASCII[character - 0x20][index]);    // display next column of pixels for this character
  }
  LcdWrite(LCD_D, 0x00);                                // display a blank space after character
}

void LcdClear(void)                                     // display a blank screen
{
  LcdWrite(LCD_C, 0x40 );                               // command to set Y cursor position to 0
  LcdWrite(LCD_C, 0x80 );                               // command to set X cursor position to 0
  for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
  {
    LcdWrite(LCD_D, 0x00);                              // display a blank column of 8 pixels
  }                                                     // the LCD automatically steps to the next position
}

void LcdInitialise(void)
{
  pinMode(PIN_SCE, OUTPUT);                                        // set the chip select pin to be an output
  // pinMode(PIN_RESET, OUTPUT);
  pinMode(PIN_DC, OUTPUT);                                         // set the DC pin to be an output
  pinMode(PIN_SDIN, OUTPUT);                                       // set the MOSI pin to be an output
  pinMode(PIN_SCLK, OUTPUT);                                       // set the SPI clock pin to be an output
  // digitalWrite(PIN_RESET, LOW);
  // digitalWrite(PIN_RESET, HIGH);
  LcdWrite(LCD_C, 0x21 );                                         // put LCD in Extended Commands mode.
  LcdWrite(LCD_C, 0xA8 );                                         // Set LCD Vop (Contrast). 0x80 - 0xFF (0xA8 for 1300, 0xCC for 1310)
  LcdWrite(LCD_C, 0x05 );                                         // Set Temp coefficent. 0x04 - 0x07
  LcdWrite(LCD_C, 0x16 );                                         // LCD bias mode 1:48.  0x10 - 0x17
  LcdWrite(LCD_C, 0x20 );                                         // LCD Basic Commands
  LcdWrite(LCD_C, 0x0C );                                         // put LCD back in normal mode.
}

void LcdString(char *characters)                        // display a sting of characters on LCD
{
  while (*characters)
  {
    LcdCharacter(*characters++);
  }
}

void LcdWrite(byte dc, byte data)                       // display a byte as 8 vertical pixels
{
  digitalWrite(PIN_DC, dc);                             // control the DC pin - should be data
  digitalWrite(PIN_SCE, LOW);                           // apply chip select to LCD
  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);         // send byte as serial bit stream
  digitalWrite(PIN_SCE, HIGH);                          // deselect LCD
}

void setup() {
  Serial1.begin(9600);                                  // this serial port is used for controlling speech

  LcdInitialise();                                      // display a splash screen
  LcdClear();
  LcdString("    Husky   ");
  LcdString(" BUG Detect ");
  LcdString("    and     ");
  LcdString("   SPEECH   ");
  LcdString("     by     ");
  LcdString("  DOUG WONG ");
  delay(1000);                                          // show the splash screen for 1 second
  LcdClear();

  //  if (!LoRa.begin(915E6)) {           //start LoRa radio
  //    LcdString("LoRa fail");
  //    while (1);
  //  }

  //  LcdClear();
  news = 1;
  critr = 4;          //3=Lora, 1=B1, 2=2B, 4=Husky, 5=Spiderman, 6=Cindy, 7=Grashopper, 8=Ladybug, 9=background
}

void loop()                         // main loop has a conversation
{

  char buf[128];                  // for text-to-speech text

  LcdClear();

  LcdWrite(LCD_C, 0x80 );  // set X Command
  LcdWrite(LCD_C, 0x41 );  // set Y Command
  LcdString("ID ");
  critss = String(critr);
  critss.toCharArray(crits, 2);
  LcdString(crits);
  LcdString("   ");
  delay(400);
  // Check to see if time to send another message
//  if (news) {

    //      news = 0;

    if (critr == 1) sprintf( buf, "[h0][f1][m51][t2][s7]I see one bee");
    if (critr == 2) sprintf( buf, "[h0][f1][m51][t2][s7]I see another bee");
    if (critr == 3) sprintf( buf, "[h0][f1][m53][t5][s6]Lora here, How are you?");
    if (critr == 4) sprintf( buf, "[h0][f1][m51][t2][s7]Hello, this is Husky.");
    if (critr == 5) sprintf( buf, "[h0][f1][m51][t2][s7]I see a spyder");
    if (critr == 6) sprintf( buf, "[h0][f1][m51][t2][s7]I see a Sicada");
    if (critr == 7) sprintf( buf, "[h0][f1][m51][t2][s7]I see a Grasshopper");
    if (critr == 8) sprintf( buf, "[h0][f1][m51][t2][s7]I see a Ladybug");

    //    if (critr == 9) sprintf( buf, "[f1][m53][t5][s5]Hey Cristal, Background check.");

    speak(buf);

    waitForSpeech();

    LcdWrite(LCD_C, 0x80 );  // set X Command
    LcdWrite(LCD_C, 0x48 );  // set Y Command
    if (critr == 1) LcdString("OhBeeOne");
    if (critr == 2) LcdString("Two Bee");
    if (critr == 3) LcdString("Lora");
    if (critr == 4) LcdString("Husky");
    if (critr == 5) LcdString("Spiderman");
    if (critr == 6) LcdString("Cindy Cicada");
    if (critr == 7) LcdString("Grasshopper");
    if (critr == 8) LcdString("Ladybug");
  
    delay(400);

    if (critr == 1) sprintf( buf, "[h0][f1][m52][t4][s8]]Hi Husky, I am Oh bee wun!");
    if (critr == 2) sprintf( buf, "[h0][f1][m53][t8][s7]Hi Husky, I am Too Bee!");
    if (critr == 3) sprintf( buf, "[h0][f1][m53][t5][s6]Hey Husky, Lora here, Are you ready to recieve?");
    if (critr == 4) sprintf( buf, "[h0][f1][m51][t2][s7]I an looking for bees bugs and beetles");
    if (critr == 5) sprintf( buf, "[f1][m52][t6][s8]Hi Husky, I am Spyderman!");
    if (critr == 6) sprintf( buf, "[f1][m3][t7][s7]Hi Husky, I am Sindy Sicada!");
    if (critr == 7) sprintf( buf, "[f1][m20][t3][s8]Hi Husky, I am Grasshopper!");
    if (critr == 8) sprintf( buf, "[f1][m55][t6][s6]Hi Husky, I am Ladybug!");

    speak(buf);

    waitForSpeech();
    delay(4000);

    //critter sequence

    if (critr == 8) critr = 4;
    if (critr == 7) critr = 8;
    if (critr == 6) critr = 7;
    if (critr == 5) critr = 6;
    if (critr == 2) critr = 5;
    if (critr == 1) critr = 2;
    if (critr == 4) critr = 1;

    LcdClear();
    LcdWrite(LCD_C, 0x80 );  // set X Command
    LcdWrite(LCD_C, 0x41 );  // set Y Command
    LcdString("ID ");
    critss = String(critr);
    critss.toCharArray(crits, 2);
    LcdString(crits);
    LcdString("   ");



    //    LoRa.beginPacket();
    //    LoRa.print(critr);
    //    LoRa.endPacket();


    // Now listen for response

    //      while (packetSize = 0) {                //this loop needs a get out of jail
    //        packetSize = LoRa.parsePacket();
    //      }
    //        LoRaChar = (char)LoRa.read();
    //        LcdWrite(LCD_C, 0x80 );  // set X Command
    //        LcdWrite(LCD_C, 0x41 );  // set Y Command
    //        LcdString("ACK ");
    //        itoa(critr, crits, 2);
    //    critss = String(critr);
    //    critss.toCharArray(crits,2);
    //    LcdString(crits);
    //    LcdString("   ");

    //      LcdWrite(LCD_C, 0x80 );  // set X Command
    //      LcdWrite(LCD_C, 0x44 );  // set Y Command
    //      LcdString("RSSI ");
    //      rsi = (char)LoRa.packetRssi();
    //      rsis = String(rsi);
    //      rsis.toCharArray(rsia,4);
    //      LcdString(rsia);

    //    LoRa.flush();
    //    delay(100);
    //    news = 1;
    //  }
//  }
}

Discussion
Progress is being made towards a fully functional system, but there are hurdles with LoRa and I have not tackled the Nicla vision yet. These breadboard systems essentially use the same schematic as the one published in the previous blog. Unfortunately the PCBs have not arrived, so I have to suffer through breadboard lashups until they do. I thought the LoRa connection would be easy since I have done one before, but it looks like I have a non-functional radio and troubleshooting is difficult. It takes a surprising amount of time to adjust and tune up all the voices but they need to at least be somewhat understandable. It isn't enough to get the pitch and speed right, each word can require phonetic adjustment. It is kind of fun to see what is possible, but long passages of text will rapidly get tedious, given that you may need to listen to listen to a long segment, then reprogram it with a new guess, then do it all again. There are a bunch of options for each syllable, so it can take a lot of time to nail the effect you want.

Status and Next Steps - The PLan
1 The first blog introducing the project and the main characters with some speech synthesis is complete.
2 The second blog demonstrating machine learning of various insects and schematics of the interface PCB is complete.
3 This is the third blog which shows the build of 2 breadboard systems and programs that set up interfaces between the various sub-systems. It also introduces multi-voice synthesis.
4 Electronic systems build of 3 nodes, node software, 3D printed case design
5 Farmer system demonstration, Bee Keeper system demonstration, project summary and discussion

Links:

 Two Bee Or Not Two Bee 

 Save the Bees - Machine Learning 

 Name That Bee 

 Bee The PCBee 

 Show Me The Bee! 

 The Lora & Husky Show 

 Image Conversion to Integer Array for LCD Display 

 LoRa Transmission of Images 

 Save The Bees Wrap Up - Blog 9 

 Save The Bees - Design Challenge 

  • Sign in to reply
Parents
  • ralphjy
    ralphjy over 2 years ago

    Nice "animation".  That's a great lash up with your DSLR.  I did something similar mounting a HuskeyLens to my iPhone for videos, but nowhere as neat as your setup.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • ralphjy
    ralphjy over 2 years ago

    Nice "animation".  That's a great lash up with your DSLR.  I did something similar mounting a HuskeyLens to my iPhone for videos, but nowhere as neat as your setup.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • dougw
    dougw over 2 years ago in reply to ralphjy

    I had to use a phone to take a picture of the two cameras in the image ...Relaxed

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • dougw
    dougw over 2 years ago in reply to ralphjy

    Note that the white camera bracket is a friction fit for a GoPro mount, so if the big camera lens gets extended accidentally, it will push the Huskylens off the bracket without damaging the lens motors and gears.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • ralphjy
    ralphjy over 2 years ago in reply to dougw

    Good idea.  Should always plan for accidents - especially with high value hardware...

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • dougw
    dougw over 2 years ago in reply to ralphjy

    It isn't actually a DSLR, but it has a phenomenal lens that can focus this close as well as take pictures of the moon.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube