Under what circumstances will a full node disconnect a peer? I know a full node will disconnect from a node if that node "misbehaves". For example, a node's connection will be dropped if it sends too many messages that don't follow the rules (what rules?) and nodes that send a lot of expired, duplicate, or otherwise useless messages. What other reasons do full nodes disconnect from a peer?

For example, do full nodes disconnect from connections that don't send enough data?
For a node to be disconnected the default threshold of banscore is 100. In versions prior to v0.18, the default time to keep the misbehaving peer from reconnecting is 86,400 seconds or 1 day. However, this was circumvented by attackers with multiple IP addresses. 

v0.18 release, allows peers that your node automatically disconnected for misbehavior (e.g. sending invalid data) to reconnect to your node if you have unused incoming connection slots. If your slots fill up, a misbehaving node will be disconnected to make room for nodes without a history of problems (unless the misbehaving node helps your node in some other way, such as by connecting to a part of the Internet from which you don't have many other peers). 

Following are the reasons for disconnection, or increasing the banscore.


Peers which provide a chain with less work than the minimum-chain-work during IBD are  disconnected
If the node is providing invalid data like mutated block or data not meeting consensus requirements
If the compact block had a valid header, but contained invalid txs, the peer should not be punished
Ban outbound (but not inbound) peers if on an invalid chain.
Invalid header, invalid block checkpoint, and invalid previous block will result in outright ban
If previous block is missing, the banscore is incremented by 10. This is done so as to prevent DoS attacks
If the peer sends a getblocktxn with out-of-bounds tx indices it will result in a ban
There are other items related to bloom version and bloom size which might result in ban
First message should be a version message and each connection can send version message only once. If not, the banscore is incremented by 1
If the node is sending addr messages with more than 1000 addresses, then banscore is incremented by 20
Sending inv messages that exceeds the max size, then banscore is incremented by 20.
Sending header messages with more than 2000 elements, resulting in incrementing banscore by 20.
Nodes must NEVER send a data item > 520 bytes or misbehaving score is incremented by 100


There are other couple reason which might have been ommited. You can search "misbehaving" in the netprocessing.cpp file for all the reasons.


  Do full nodes disconnect from connections that don't send enough data?


Not particularly but somewhat yes. When the chain tip does not advance for over 30 minutes, the full node assumes that the tip may be stale and hence will try to connect to an additional outbound peer. There is a periodic check that ensures that if the extra peer connection is in use, the node will disconnect the peer that least recently announced a new block.