Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

CC1101 to ATMEGA328P pinning #11

Closed
GlennWardle opened this issue Mar 18, 2021 · 38 comments
Closed

CC1101 to ATMEGA328P pinning #11

GlennWardle opened this issue Mar 18, 2021 · 38 comments

Comments

@GlennWardle
Copy link

Can you please tell me the pinning between ATMEGA328P (standard UNO) and the CC1101. I don't fully understand atm328_pins.h which I presume sets this. Thanks

@ghoti57
Copy link
Owner

ghoti57 commented Mar 18, 2021

There is no definite answer to your question :-)

Firstly - have you looked at the README for the firmware?
Are you using the custom evofw3_avr board definitions?
You cannot build evofw3 with the standard Arduino board definitions.

OK assuming you're doing this....

The reason there is no definite answer is that evofw3 can be made to run on a number of avr platforms connected to a cc1101.
The problem is that many of the off-the-shelf packages make the connections in different ways.

The options in the evofw3_avr board options select one of the combinations I've seen or have had reported.
The options are actually controlled from evofw3_avr:boards.txt
This file specifies the values for GDO0, GDO2 and CCSEL which control xxx_pins.h

The following options are currently supported

Note the code DOES NOT use Arduino pin numbers - these are the avr pin identifiers and these are the values specified in xxx_pins.h

atmega328p
MOSI-B3 MISO-B4 SCK-B5 CSN-B2
nano: GDO0-INT1(D3) GDO2-INT0(D2)
pro: GDO0-INT0(D2) GDO2-INT1(D3)

atmega32u4
MOSI-B2 MISO-B3 SCK-B1
GDO0-TXD1(D3) GDO2-RXD1(D2)
ProMicro: CSN-B6
SHA: CSN-B0

If you've got an off the shelf package then one of these will probably work.
If you're making your own from components then, depending which processor you have, I'd go for the either atmega328p:nano or atmega32u4:ProMicro as they're the most common options.

Note:
atmega328p systems MUST have a 16MHz clock - it won't run on 8MHz.
atmega32u4 systems will run on an 8Mhz system

@GlennWardle
Copy link
Author

GlennWardle commented Mar 18, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented Mar 18, 2021

Does this count as "pro" pinning?
It depends where you connect GDO0/GDO2 - I think you're suggesting the pro connections but I'm not certain.

Since you're in control connect GDO0 to D3 and GDO2 to D2 and the SPI port as specified- then it'll be 'nano' pinout

atmega328p
MOSI-B3 MISO-B4 SCK-B5 CSN-B2
nano: GDO0-INT1(D3) GDO2-INT0(D2)

@ghoti57
Copy link
Owner

ghoti57 commented Mar 21, 2021

Have you got this working now?

@GlennWardle
Copy link
Author

GlennWardle commented Mar 21, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented Mar 22, 2021

That's because you're not using the custom board definitions.
Checkout the README on evofw3.

Install the evofw3_avr custom board definitions and use them.
There's no need to edit any code.

DO NOT use the Arduino board definitions - that way will cause pain and confusion when something doesn't work

@GlennWardle
Copy link
Author

GlennWardle commented Mar 29, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented Mar 29, 2021 via email

@GlennWardle
Copy link
Author

GlennWardle commented Mar 29, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented Mar 29, 2021

Ok,

all the information you want is available in message.c.

I suggest you add a function in this file e.g.
uint8_t msg_glenn( struct message *msg)
Which can analyse each message.

The easiest place to call this so it happens once per message is in gateway.c

  if( !nRx ) {
     msg_glenn( rx );
     msg_free( &rx );
   }

Pay attention to the bits that are set in rxFields for which addresses are valid. (see msg_rx_process for an example)
and also (in case a bad message gets through) that msg->error==MSG_OK

If you want to send a message because you've identified a trigger condition call tx = msg_alloc(), populate the message and then call msg_tx_ready(&tx) (or whatever you want to do). Don't try to free tx after calling msg_tx_ready - tx will be null :-)

@ghoti57
Copy link
Owner

ghoti57 commented Mar 29, 2021

actually a better place to call your code would be

   // If we get a message now we'll start printing it next time
    rx = msg_rx_get();
    if( rx ) msg_glenn( rx );

Now you must test msg->error==MSG_OK before you do anything with the message

However now you can get evofw3 to append text to the message when it prints it so you can debug your logic.
to do that add more lines to _MSG_ERR_LIST in message.h. Keep the text string short.

Now when you recognise trigger conditions in you code you can set msg->error to one of your new values and the text will be appended to the message when it's printed.

@GlennWardle
Copy link
Author

GlennWardle commented Mar 29, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented Mar 29, 2021

Actually just realised that your function does not usefully return anything so it looks like
void msg_glenn( struct message *msg )

@GlennWardle
Copy link
Author

GlennWardle commented Mar 29, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented Mar 29, 2021

There should be no problem doing the analysis in a single MCU within the existing evofw3 code.
As long as you only print short fixed messages using the method I suggest.

Just remembered - to get the custom text appended to the messages you'll have to set uint8_t trace0=TRC_ERROR; in cmd.c
That will also make it print bad messages

@ghoti57
Copy link
Owner

ghoti57 commented Mar 29, 2021

Forget trying to decode the serial stream.
Everything is decoded for you in struct message in message.c

@ghoti57
Copy link
Owner

ghoti57 commented Mar 29, 2021

Something like this will get you going

void msg_glenn( struct message *msg ) {
  // Validate message
  if( !msg || msg->error!=MSG_OK )
    return;

  // only look at 3150 messages
  if( msg->opcode[0] !=0x31 || msg->opcode[1] != 0x50 )
    return;
}

@GlennWardle
Copy link
Author

Hello gohti57
I've built up two monitors using your code, one with an UNO and one with a MICRO, using two different CC1101 modules, one of which was 'native' 868MHz, and the other which needed mods to change the filters to 868MHz. Both work, but both appear to miss a ton of messages even though the RSSI figures look very good. Is there a specific CC1101 module that you can recommend? In one evening of logging, the native 868MHz version (into the Arduino MICRO) logged many hundreds of message from the Evohome contoller (device 01), the BDR91 (device 13), and the wall thermostat (device 34) but without registering a single message from any HR92 (device 04) even though I have 16 of them. Very odd.

@ghoti57
Copy link
Owner

ghoti57 commented Apr 20, 2021

Which CC1101 modules are you using?

There have been a number of issues recently with the square green ones - they appear to be made by a number of different manufacturers and the quality is variable. In particular the 26MHz crystals being used don't seem to be very accurate.

Have you tried the evofw autotune procedure.

Preferably from the Arduino GUI serial monitor, rather than any other serial program try this. (make sure line ending is set to NL & CR)

Send the following command (including !)
!FT

This will try to find the optimum frequency parameters for your cc1101.
You will see good AND bad received messages reported and lines that look like
!C D 21 65 5A

This will run for about 40 minutes
You can check whether it's complete at any time by sending
!F

It will report the current frequency parameter and, if it's still searching, will report "Tuning"

Assuming it works save the frequency with
!FS

@ghoti57
Copy link
Owner

ghoti57 commented Apr 20, 2021

Which processor are you using?

The atmega328p modules (nano etc) are forced to implement a SW UART mechanism for RX and it's not as good as using a HW UART which is possible on ATMega32U4 modules (Pro Micro, Leonardo etc) .

I'm selling these modules SSM
I've abandoned the green CC1101 modules as they're so unreliable.

These red cc1101 modules all seem to come from one manufacturer.

search for cc1101 E07

@GlennWardle
Copy link
Author

GlennWardle commented Apr 22, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented Apr 22, 2021

Sorry currently no readme on tuning.

It's one of the topics I want to add to the wiki.

@GlennWardle
Copy link
Author

Hello ghoti57
Further progress... I've managed to call a function when it receives a 3150 message - which is great. What I need to do now is get my function to look at the transmitting device IDs (in a switch/case statement), so I can build up a map of how each TRV is doing for heat demmand. I am struggling to understand how to extracted the device ID (in decimal I presume) from the message string. Please - can you tell me the best way to pull out the 6 digit ID (of the first address) from the message string. Thanks again for your help.

@ghoti57
Copy link
Owner

ghoti57 commented Apr 24, 2021

here's the message structure in message.c
`struct message {
uint8_t state;
uint8_t count;

uint8_t fields; // Fields specified in header
uint8_t rxFields; // Fields actually received
uint8_t error;

uint8_t addr[3][3];
uint8_t param[2];

uint8_t opcode[2];
uint8_t len;

uint8_t csum;
uint8_t rssi;

uint8_t nPayload;
uint8_t payload[MAX_PAYLOAD];

uint8_t nBytes;
uint8_t raw[MAX_RAW];
};`

Look at msg_print_field() to see how to determine which of the three address fields are valid using rxFields
look at msg_print_addr() to see how to use msg_get_addr() to get the device class and id from addr[3][3].

If you really want a single value for the complete address you'll need something similar to msg_get_addr() that builds a uint32_t from all 3 bytes in a similar way to msg_get_addr()

One comment is I'd call your code for EVERY received message and put the tests to decide if you're interested in it in the function. This means gateway.c has minimal logic and all your logic is together inside message.c.

@GlennWardle
Copy link
Author

Hello ghoti57
I'm really sorry to hassle you, but I'm affraid all the stuff on structures is currently beyond me, and I've tried and failed, to convert the id into a single uint32_t by grabbing a copy of it in msg_print_addr (which I planned to compare against each of my 16 TRV 6 digit IDs). Please, is there a 'clever line of code' I can pop in somewhere that gives me the source id so it can be compared directly against each of my TRV IDs? - sorry to be a nuisance.

@ghoti57
Copy link
Owner

ghoti57 commented Apr 27, 2021

Hi Glenn,

you need something like this (call msg_rx_hook() from gateway.c

Some of the code is to make it easier for you to reuse with say different address fields or different opcodes

struct my_trv_data {
  uint32_t id;

  // Any other data fields you need for whatever you want to keep track of for each TRV
}

static struct my_trv_data myTRVs[] = {
  // List the IDs of your TRVs here (don't put leading zeroes in)
  { .id = 12345 },
  { .id = 12346 },
  { .id = 213456 }, 
  // etc.
  // Must be last
  { .id=0xFFFFFFFF }
};

static struct my_trv_data * find_trv( uint32_t id ) {
  struct my_trv_data *trv;
  
  for( trv=myTRVs ; trv->id!=0xFFFFFFFF; trv++ ){
    if( id==trv->id )
      break;
  }

  if( trv->id==0xFFFFFFFF )
    trv = NULL; // Not a message from one of listed TRVs

  return trv;
}
 
#define CLASS_GWAY 18
#define CLASS_CTLR  1
#define CLASS_TRV   4

void msg_rx_3150( struct message *msg ) {
  uint8_t class;
  uint32_t id;

  // extract the first address (class:id) from the message
  msg_get_addr( msg->addr[0], &class, &id );

  if( class==CLASS_TRV ) {
    struct my_trv_data *trv = find_trv( id );
    if( trv != NULL ) {
      // do something with the current TRV

      // do something to do with the system
  }  
}

void msg_rx_hook( struct message *msg ) {
  uint16_t opcode = ( msg->opcode[0]<<8 ) | msg->opcode[1];

  switch( opcode ) {
    case 0x3150:   msg_rx_3150( msg );   break;
    // Handle any other opcodes here
  }
}
 

@GlennWardle
Copy link
Author

GlennWardle commented May 5, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented May 6, 2021

Glad you're making progress.

However, I don't believe you should have been modifying the msg_print functions. Doing this precludes all possibility is just 'switching on' print for debug purposes at some time in the future.

All your references to decimal and hex suggest to me you don't understand what the existing code does and how to use the content of the message structure. Hex and decimal are irrelevant. All your logic should be based on the BINARY values returned by msg_get_addr.

I suspect you're making it more difficult than necessary.

Look at my suggested code again

@GlennWardle
Copy link
Author

GlennWardle commented May 6, 2021 via email

@ghoti57
Copy link
Owner

ghoti57 commented May 7, 2021

Decoupling from the serial port is high on my to-do list for the next release

@Ierlandfan
Copy link

Hi,

is there a way to check whether the CC1101 is working or correctly connected? (I am using a VM with attached Pro Micro and CC1101

Connections:

CC 1101 Pro Micro
VCC VCC
GND GND
MOSI- B2 > 16
SCK- B1 >15
MISO- B3 >14
GDO02 RXD1(D2)
GDO00 TXD1(D3)
CSN B6 >10

The Pro Micro is identified in Ubuntu as "/dev/ttyACM0 - SparkFun_evofw3_atmega32u4" so that's good.
If I plug it in a Windows machine and use the Arduino IDE for autotune then there's no output on the serial .
In Windows the port I have is identified as " USB-Serial" so I am a little confused whether it is working ok and how to aututune the CC1101 (Green board) on the Arduino IDE.

@hughb8on
Copy link

hughb8on commented May 19, 2021

I have put together two CC1101/SS Micro HGI80 emulators recently, one red and one green. I have connected my pins differently from those you are using - I see you're using the ones suggested by ghoti57.

My connections differ for GDO0 and GDO2 only; this is what I am successfully using: -

Green CC1101 SS Micro
Vcc 3v3
Gnd Gnd
MOSI MO (D16)
SCLK SCK (D15)
MISO MI (D14)
GDO2 Rx (D0)
GDO0 Tx (D1)
CSN D10

Red CC1101 SS Micro
Vcc 3v3
GDO0 Tx (D1)
CSN D10
SCK D15
MOSI MO (D16)
GDO1 (MISO) MI (D14)
GDO2 Rx (D0)
GND Gnd

The CC1101 pins above are in the order top-to-bottom with the boards chip-side-up and the pins to the left.

Edited slightly: If you are using a different ATMEGA32U4 board from me then I would suggest you just make sure you connect GDO0 to your board's Tx pin and GDO2 to its Rx pin - but that seems to be what you have done, so ...

@Ierlandfan
Copy link

Well, I 've checked the CC1101 and on another board it's receiving packages so seems ok.
I've noticed that when I not connect the CC1101 ther serial monitor says "Evofw3 0.7.0" or similar.
When I connect the CC101 to the Arduino there's nothing on the serial port. Is that a sign that it's wrongly connected?

@hughb8on
Copy link

If you are using the custom board definitions for the pro micro, as per the instructions, then I guess incorrect connections is still a possibility.

Pin naming can confusing; can you confirm that you are connecting GDO0 to D1 (aka Tx aka PD3) not D3 as you posted, and also that you have GDO2 connected to D0 (aka Rx aka PD2) not D2 as you posted?

On the boards I have seen, the silk screen printing clearly indicates the Rx and Tx pins; make sure you are using those, not the pins marked "2" and "3" which are D2 (aka SDA aka PD1) and D3 (aka SCL aka PD0). Nothing needs to be connected to those two.

I have no idea what your level of experience is so please forgive if I'm telling you things which are already obvious.

@arjenhiemstra
Copy link

arjenhiemstra commented May 19, 2021

Not sure if the following was really the culprit at my side but I experienced the same issue as ierlandfan. After disconnecting the CC1101, sending a !ER command to reset the EEPROM, connecting the CC1101 again it worked.
I noticed that at first it tried to load bogus settings to the CC1101, after the EEPROM reset all was working just fine

@ghoti57
Copy link
Owner

ghoti57 commented May 19, 2021

Hi,

is there a way to check whether the CC1101 is working or correctly connected? (I am using a VM with attached Pro Micro and CC1101

Connections:

CC 1101 Pro Micro
VCC VCC
GND GND
MOSI- B2 > 16
SCK- B1 >15
MISO- B3 >14
GDO02 RXD1(D2)
GDO00 TXD1(D3)
CSN B6 >10

The Pro Micro is identified in Ubuntu as "/dev/ttyACM0 - SparkFun_evofw3_atmega32u4" so that's good.
If I plug it in a Windows machine and use the Arduino IDE for autotune then there's no output on the serial .
In Windows the port I have is identified as " USB-Serial" so I am a little confused whether it is working ok and how to aututune the CC1101 (Green board) on the Arduino IDE.

Using this image as a reference

CC1101 Pro Micro
GND GND
3V3 Depends on actual board
GDO0 1
GDO2 0
MOSI 16
MISO 14
SCK 15
CSN 10

@ghoti57
Copy link
Owner

ghoti57 commented May 19, 2021

Ways you can check the cc1101 configuration is
!F
Unless you've run autotune this should report F=21656A

If it prints anything else enter
!ER
and IMMEDIATELY unplug the usb

plug the USB back in and try
!F again

Any error here suggests the SPI connections are wrong.

Also failure to report the evofw3 version string on initial connection is also a suggestion that the SPI connection is having problems

There can also be minor problems with the USB interface of the atmega32u4.
Closing and opening the computer serial port doesn't cause a restart (I'm working on it)

You can get it to restart by changing the baudrate from the computer TWICE.
Note it doesn't matter what baudrate you actually specify on the computer - it's a pure USB connection (unlike the nano boards)
Except 1200 baud will trigger the pro micro bootloader.

@Ierlandfan
Copy link

If it prints anything else enter
!ER
and IMMEDIATELY unplug the usb

That did the trick!

@ghoti57 ghoti57 closed this as completed May 26, 2021
Repository owner locked and limited conversation to collaborators May 26, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants