-
Notifications
You must be signed in to change notification settings - Fork 240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HC-12 433MHz wireless serial module (HCMODU0054) #86
Comments
Ciao Mortimer! PJON_ASK is an obsolete version of PJON integrated in The PJON repo since The 3.0 as a Strategy. In your particolar case I would use the ThroughHardwareSerial Strategy! If I understood correctly your modules can work with serial I/O. I agree would be nice to have them workin also with OverSampling or better SoftwareBitBang! I will be soon back from vacation and I will look for this hardware to give it a try! Thank you for your support :) |
Hi @MortimerNeuss have you got better results with ThroughHardwareSerial strategy? Happy tinkering |
Not yet. But the next Weekend is coming :) |
I think I got it working. I tried it this evening and it seems to did the job. It is a bit hard to debug as the RX/TX Lines are now connected to the HC-11 and therefore I have no Arduino Serial Monitor anymore, but the blinkpattern looks like device A is sending something and device B is receiving aparently an B, because it does blink too. I will hook up a 16x2 OLED Display on the Weekend to have a data feedback on what is actually received. Thank you for your motivation! Nice Project. |
@MortimerNeuss this is a good news!! Which is the maximum range of those transceivers?? Are you using ThroughHardwareSerial ?? Happy tinkering |
Hello I spend the past weekend on the modules again and found out that they are not HC-11 but the AT-Command for the Version said it are in fact HC-12 (therefore the Edit in the Title and the Post). To sum it up: I got no step further but learned a lot. I tried to use the HardwareSerial Mode without luck. I got the SoftwareSerial again working but very slow. Sometimes the output showed weird Characters for some reason and I suspected it might be a raw error. I found in a youtube comment this:
I therefore set the Baud-Rate to 2400 as well to avoid any problems with that. I tried the code provided by this instructable (Exercise files here) and that worked like expected by just using the Arduino SoftwareSerial Function. It is slow, but does the job in both directions. But again: I didnt got the HC-12 working with PJON. Any hints for me at that point? I'm at work, so I will attach the current Code with PJON this evening. Greetings |
Ciao @MortimerNeuss , yes the errors you detect are raw errors / interference. The faster you transmit the higher is the chance to get a transmission error, in general with radio signals. Seems the hardware you are using is compatible only with SoftwareSerial? If no, probably this could be the reason and a ThroughSoftwareSerial strategy could be necessary to have your hadware compatible. I can work on it because was in any case on the list on new things to be added :) |
CIao @MortimerNeuss finally thanks to the work of girgitt, ThroughHardwareSerial, is now ThroughSerial and supports the use of both Serial and SoftwareSerial. Give it a try: https://github.com/gioblu/PJON/tree/master/strategies/ThroughSerial Simply pull from master (still unreleased) |
Thank you for the update, I will check it out after Dinner. Nice Contribution! |
Ciao @MortimerNeuss seems you should cross the serial pins? rx -> tx and tx -> rx? |
@MortimerNeuss would be more effective to start with the use of this sketches:
Nice build! |
After your first reply I sat back at the table, cleaned up the code and switched from Serial to SoftwareSerial again as ThroughSerial now accepts SoftwareSerial. Previously HardwareSerial of course only accepted the original Serial. This is working fine now. Yet, using the Hardware-Serial is still not working for me somehow. I will try the Sketch from your second post on the Weekend. See it in action here. Here is the working Code with SoftwareSerial (for others in the future): //HC-12 messenger send/receive
#include <PJON.h>
#include <SoftwareSerial.h>
#include "Wire.h"
#include "OLedI2C.h"
OLedI2C LCD;
SoftwareSerial mySerial(2, 3); //RX, TX
int ID_sendto = 33;
float received = 0;
// Bus id definition
uint8_t bus_id[] = {0, 0, 0, 1};
// PJON object - 2 pin over-sampled physical layer
//PJON<ThroughHardwareSerial> bus(bus_id, 66);
//PJON<SoftwareBitBang> bus(bus_id, 66);
PJON<ThroughSerial> bus(bus_id, 66);
void setup() {
Serial.begin(9600);
mySerial.begin(2400);
//not needed while ThroughSerial
//bus.set_pins(2,3);
bus.strategy.set_serial(&mySerial);
bus.begin();
bus.send_repeatedly(ID_sendto, "B", 1, 1000000);
bus.set_receiver(receiver_function);
Wire.begin();
LCD.init();
LCD.sendString("Ready...",0,0); // (col, row);
}
void receiver_function(uint8_t *payload, uint8_t length, const PacketInfo &packet_info) {
Serial.print("Receiver bus id: ");
Serial.print(packet_info.receiver_bus_id[0]);
Serial.print(packet_info.receiver_bus_id[1]);
Serial.print(packet_info.receiver_bus_id[2]);
Serial.print(packet_info.receiver_bus_id[3]);
Serial.print(" - device id: ");
Serial.println(packet_info.receiver_id);
Serial.print("Sender bus id: ");
Serial.print(packet_info.sender_bus_id[0]);
Serial.print(packet_info.sender_bus_id[1]);
Serial.print(packet_info.sender_bus_id[2]);
Serial.print(packet_info.sender_bus_id[3]);
Serial.print(" - device id: ");
Serial.println(packet_info.sender_id);
received++;
//LCD.sendString(received,0,1); // (col, row);
LCD.sendFloat(received,4,0,7,0);
digitalWrite(13, HIGH);
delay(30);
digitalWrite(13, LOW);
delay(30);
digitalWrite(13, HIGH);
delay(30);
digitalWrite(13, LOW);
delay(220);
/*
// Spinning Indicator
if ( (received % 2) == 0) {
LCD.sendString("-",15,0); // (col, row);
}else{
LCD.sendString("/",15,0); // (col, row);
}
*/
}
void loop() {
/*
if(Serial.available() > 0){//Read from serial monitor and send over HC-12
String input = Serial.readString();
//mySerial.println(input);
bus.send(33, "Ola, this is a test!", 20);
}
*/
/*
if(mySerial.available() > 1){//Read from HC-12 and send to serial monitor
String input = mySerial.readString();
Serial.println(input);
}
*/
delay(20);
bus.receive(1000);
bus.update();
}
|
@MortimerNeuss Fantastic! This is a great achievement :). Great experiment. I now noticed that the example I proposed you should be renamed. |
Shocking you made it work in 12 hours after I pushed an unreleased version of this strategy ;) |
I would love to help you out with Demos and General Wiki-Contribution, sure! uint8_t curs = 6;
for(uint8_t i = 0; i < length; i++){
LCD.cursPos((6+i),1);//
LCD.sendData((char)payload[i]);
} This works. But doing this, gives me weird chars: LCD.cursPos(6,0);
LCD.sendData((uint8_t)packet_info.receiver_id); How do I have to convert it correctly? Also, I have this line, thats works fine bus.send_repeatedly(ID_sendto, "AB", 2, 1000000); But when I do, it seems he is sending wrong chars: const char txt = "AB";
//uint16_t send_repeatedly(xuint8_t id, const char *string, ... )
bus.send_repeatedly(ID_sendto, txt, 2, 1000000);
I was not able to find an example where I can feed bus.send, because I currently can only make it correctly working when I hardtype the Strings into the Functions rather than pasting dynamic values into it. Is it a char? const char? String? uint8_t?
So, as you can see, I'm the best person for your wikis beginner guide, as I am myself a beginner :D Mortimer |
the send function receives an array of characters so something like: char message[4] = { 'C', 'I', 'A', 'O' };
// or if static
char message[] = "CIAO"; The type is See the SendArbitraryValues example: https://github.com/gioblu/PJON/blob/master/examples/Network/SendArbitraryValues/Transmitter/Transmitter.ino Speaking about the receiver_id in the packet_info we are spaking about a byte. You can print various representations of a byte like: Serial.print(packet_info.receiver_id, BIN);
Serial.print(packet_info.receiver_id, DEC);
Serial.print(packet_info.receiver_id, HEX); I think you are looking for the decimal value of that byte, and so the device id number. It is a pleasure to help, feel free to ask! |
CIao @MortimerNeuss see above answer and about the pseudocode I missed before: typedef struct {
char content[4];
} Element;
Element stack[4];
// Write basically the content of the first Element of the stack
stack[0].content[0] = 'C';
stack[0].content[1] = 'I';
stack[0].content[2] = 'A';
stack[0].content[3] = 'O';
// Or the same using memcpy(destination, source, length) function
char tx_string[] = "CIAO";
memcpy(stack[0].content, tx_string, 4);
// Send the first element of the stack
bus.send_repeatedly(44, stack[0].content, 4, 1000000); This is working and tested code with the actual master! |
I still dont get the packet_info.receiver_id type part: sprintf (buffer, "%c", packet_info.receiver_id);
int dec = (int)packet_info.receiver_id;
//LCD.sendData(dec); //!
//LCD.sendData(buffer); //B
//LCD.sendData(buffer[0]); //!
LCD.sendString(buffer,6,0); //! As you can see, sometimes I get a ! and sometimes a B. I guess when I see the B, that means that it must be the first char of the Byte Notation B00100001 (dec=33). I tried out Binary to int dec converter but got only the ! back. I tried casting packet_info.receiver_id to an int, to a String, to a Char-Array. It might be that the OLED-Display Lib is the problem, but I cant display the ID. What am I missing? |
Looking at the documentation of LiquidCristal library i think you should use: LCD.print(packet_info.receiver_id, DEC); |
@MortimerNeuss should be the right call. |
@sadly, I dont use a standard Liquid Cristal Display but an OLED Display. Because of that I'am using this lib. As you can see, I am very limited on what I can feed into the Display: void sendCommand(unsigned char command);
void sendString(const char *String, uint8_t col, uint8_t row);
void sendFloat(float digit, uint8_t dec, uint8_t nad, uint8_t col, uint8_t row);
void sendData(unsigned char data);
void clearLcd();
void cursPos(uint8_t, uint8_t); // cloumn, row
void scrollString(char* message, byte row, unsigned int time); //written by Nathan Chantrell http://nathan.chantrell.net/
void lcdOff();
void lcdOn();
void setContrast(unsigned char contrast); // contrast should be the hex value between 0x00 and 0xFF Do you see what would match the type or what would be the easiest way to cast? Thank you so much, you are really helpfull! |
Ups, I think I unwillingly closed the thread _/ |
Ciao @MortimerNeuss so the solution seems to be the function to_string((int)packet_info.receiver_id); |
Ciao @MortimerNeuss, I am sorry, reading back all I see that simply the library you are using doesnt support to send an integer. The solution proposed above could be a solution but is not efficient as the use of the simple itoa function: #include <stdlib.h> // for itoa() call
int num = 123;
char buf[5];
// convert 123 to array of characters in buf
itoa(num, buf, 10);
// where 2 is binary representation, 10 is decimal representation, 16 hexadecimal
LCD.sendString(buf,0,0); // (col, row); So to avoid the String type complication and handle the number as an array of chars. |
Ciao Giovanni I created a small initial "bootsequence" to get more structure in my experiment (Video). The Problem sometimes is, when I start both modules at the same time, they will not listen to one another. I need to reset one to make them ping-pong back and forth (Video). It can be that I have to many delay() in my main loop that is prohibiting a smooth execution of bus.update(). I will look into it. In a further version of my code, where I already used dynamic Names as a reply while receiving data. But I have the problem that sometimes after only 3-5 msg back and forth I get errors like "Connection Lost" and "Buffer Full" (see this Video). I have not yet figured out why those Errors happen. What are reasons that connections get lost or the buffers is full and how can I avoid this? I hope I get all these problems sorted out anytime soon and then I will share with you a Wikipage on how I setup the Hardware and was able to send Data back and forth - for beginners. I hope this will help others to kickstart their projects with PJON. I like it so far! :) All the best Latest (somewhat) working Code: Sending Broadcast Messages to one another //HC-12 messenger send/receive
#include "Timer.h" // Heartbeat Function / Loop
#include "Wire.h" // I²C Interface
#include "OLedI2C.h" // OLED Display Lib by gadjet
#include <PJON.h> // Wireless Communication Lib by gioblu
#include <stdlib.h> // for itoa() call, hint by gioblu
#include <SoftwareSerial.h> // Software Serial will be passed to PJON
// We start of by creating a Software Serial Instance
SoftwareSerial mySerial(2, 3); //RX, TX
// Also a OLED Instance
OLedI2C OLED;
// This Timer will act as our Main Loop to slow down processing
Timer t;
// #############################
// Edit These two Values by Hand or use the switch
int switchID = 1; // 0 or 1
int ID_sendto = switchID == 0 ? 33 : 66 ; // !!! This is the ID we will mainly send to (hardcoded)
int ID_self = switchID == 1 ? 33 : 66 ; // !!! This is our own ID, both must be set correctly!
float received = 0; // Number of Meassages received - Is a float because the OLED can read that only
int animSpeedDelay = 50; // This is the ms Time between Animation Steps
// Buffer with IDs for the OLED
char IDself[4];
char IDsendto[4];
char IDbeacon[4] = " B";;
// Bus id definition
uint8_t bus_id[] = {0, 0, 0, 1};
PJON<ThroughSerial> bus(bus_id, ID_self);
void setup() {
itoa(ID_sendto, IDsendto, 10); // Write sendto ID to a char to make it easier to send to the OLED Display
itoa(ID_self, IDself, 10); // Write own ID to a char (same reason)
Serial.begin(9600); // Debugging of this Device via e.g. Arduino Serial Monitor
mySerial.begin(2400); // Our Software Serial Instance that will be passed to PJON, 2400 baud as the HC-12 is very bad with anything higher, so are the rumors
bus.strategy.set_serial(&mySerial); // Plug Software Serial into the amazing PJON Library
//bus.set_pins(2,3); // not needed while ThroughSerial, PJON will use the Pins defined on mySerial
bus.begin(); // All set, lets start the Service
//This can bes used for debugging. It is a raw Beacon sending "BERLIN" over and over again
//bus.send_repeatedly(ID_sendto, "BERLIN", 6, 1000000);
bus.set_receiver(receiver_function); // This will be our listener, receiving incoming data
t.every(2000, beacon); // A Timer is used as a heartbeat Function to allow slowed down repeating executions
Wire.begin(); // I²C System start
OLED.init(); // Call OLED Lib by gadjet and init system
OLED.clearLcd(); // Clear anything that might be there, for whatever reason
// Make sure, that this ID is the same as written on the device, Solves 50% of the Problems 100% of the time
OLED.sendString("My name is",0,0); // (col, row);
OLED.sendString(IDself,11,0); // (col, row);
OLED.sendString("Correct?",0,1); // (col, row);
delay(2000); // Huge Delay for giving time to read the Text
OLED.clearLcd(); // Clear the OLED of all text
//Not yet fully used, will be showing problems by PJONs Error Functions
OLED.sendString("Errortest: ",0,1);
err();
delay(1000); //Give time to read the text output
OLED.clearLcd(); //Clear the OLED of all text
}
// #################################
// Timer heartbeat Loop - Not fully used yet
void beacon(){
int broadcastTest = bus.send(BROADCAST, "Hello?", 6);
animOut(IDbeacon);
delay(300);
}
void receiver_function(uint8_t *payload, uint8_t length, const PacketInfo &packet_info) {
int num = (int)packet_info.sender_id;
char buf[5];
itoa(num, buf, 10);
animIn(buf);
OLED.sendString(" ",5,0); // (col, row);
for(uint8_t i = 0; i < length; i++){
OLED.cursPos((5+i),0);//
OLED.sendData((char)payload[i]);
}
received++;
OLED.sendFloat(received,3,0,(16-3),0);
delay(220);
//OLED.clearLcd();
}
void err(){
/*
OLED.sendString("ERR ",16-4,1); // (col, row);
delay(animSpeedDelay*2);
OLED.sendString("ERR!",16-4,1); // (col, row);
delay(animSpeedDelay*2);
OLED.sendString("ERR ",16-4,1); // (col, row);
delay(animSpeedDelay*2);
OLED.sendString("ERR!",16-4,1); // (col, row);
delay(animSpeedDelay*2);
OLED.sendString("ERR ",16-4,1); // (col, row);
delay(animSpeedDelay*2);
OLED.sendString("ERR!",16-4,1); // (col, row);
delay(animSpeedDelay*2);
OLED.sendString("ERR ",16-4,1); // (col, row);
delay(animSpeedDelay*2);
OLED.sendString("ERR!",16-4,1); // (col, row);
delay(animSpeedDelay*2);
OLED.sendString("ERR ",16-4,1); // (col, row);
delay(animSpeedDelay*6);
*/
}
void animIn(char* fromID){
OLED.sendString(" ",2,0); // (col, row);
OLED.sendString(fromID,2,0); // (col, row);
delay(animSpeedDelay);
OLED.sendString("> ",0,0); // (col, row);
delay(animSpeedDelay);
OLED.sendString(">>",0,0); // (col, row);
delay(animSpeedDelay);
OLED.sendString(" >",0,0); // (col, row);
delay(animSpeedDelay);
OLED.sendString(" ",0,0); // (col, row);
delay(animSpeedDelay);
}
void animOut(char* sendtoID){
OLED.sendString(" ",2,1); // (col, row);
OLED.sendString(sendtoID,2,1); // (col, row);
delay(animSpeedDelay);
OLED.sendString(" <",0,1); // (col, row);
delay(animSpeedDelay);
OLED.sendString("<<",0,1); // (col, row);
delay(animSpeedDelay);
OLED.sendString("< ",0,1); // (col, row);
delay(animSpeedDelay);
OLED.sendString(" ",0,1); // (col, row);
delay(animSpeedDelay);
}
void loop() {
/*
if(Serial.available() > 0){//Read from serial monitor and send over HC-12
String input = Serial.readString();
//mySerial.println(input);
bus.send(33, "Ola, this is a test!", 20);
}
*/
/*
if(mySerial.available() > 1){//Read from HC-12 and send to serial monitor
String input = mySerial.readString();
Serial.println(input);
}
*/
t.update();
bus.receive(1000);
bus.set_error(error_handler);
bus.update();
}
void error_handler(uint8_t code, uint8_t data) {
//Error Animation
err();
if(code == CONNECTION_LOST) {
OLED.sendString("LOST",12,1); // (col, row);
//Serial.print("Connection with device ID ");
//Serial.print(data);
//Serial.println(" is lost.");
}
if(code == PACKETS_BUFFER_FULL) {
OLED.sendString("FULL",12,1); // (col, row);
//Serial.print("Packet buffer is full, has now a length of ");
//Serial.println(data, DEC);
//Serial.println("Possible wrong bus configuration!");
//Serial.println("higher MAX_PACKETS in PJON.h if necessary.");
}
if(code == CONTENT_TOO_LONG) {
OLED.sendString("LONG",12,1); // (col, row);
//Serial.print("Content is too long, length: ");
//Serial.println(data);
}
}
|
Ciao @MortimerNeuss I have tested HC-12 and added full compatibility with PJON ThroughSerial. See the proposed examples here: This module have really a huge range! :) (This update will be released along with v9 soon) |
Hello
I habe some trouble getting the code to perform for me on some
HC-11HC-12 Modules.The
HC-11HC-12 comes with a microchip on board that allowes to put the module in three different modes (Passing-Mode, AT-Mode, IO-Mode). There is a great resource doc here that shows all the available command and what pins have to be set high/low.When I connect the modules to a USB2Serial Adapter and plug it into two PCs and set the SET-Pin on the Module to low (AT Mode) I am able the access both modules - no problem (At gives me an OK back). The Settings seem fine (CH01, 9600). When I put the SET-Pin to high. I am as well able to send and receive string data from both modules with their own implementation.
I tried out the PJON_ASK (as it seems simpler to use) Blink Demo with a receiver and a transmitter device without luck. Switching on off, try different TX/RX pins and switching cables, etc. didnt seem to do anything.
I had great fun this weekend with those modules, but when it comes to PJON, I'm coming to the conclusion that there might be something that I'm missing. I cant get it to work.
Are there any ideas from your point on what I could try or what I should do? I've read the Troubleshooting-Page but no change made it work.
My setup is as following:
Ubuntu 16.x
Arduino 1.0.x && 1.6.x
Arduino Nano 3.0
HC-11HC-12 ModuleOn the Arduino Nano I use the digital IO Pins 5+6 and tried swapping them back and forth already without luck. While having the PJON Code running I put the SET-Pin to heigh, so the HC-11 is in Passing-Mode. I assume that the Arduino Nano is then able to transmit the Data via Pin 5/6 to the Module.
In either case:
Thank you for this lib, even though I havnt worked it all out yet, I think it is of great benefit for the community. It looks really promising.
Sincerely
Mortimer
EDIT:
In the first draft of this post I mentioned the HC-11 Modules but the AT command for the Version is saying that those are HC-12 Modules. So... yeah...
The text was updated successfully, but these errors were encountered: